Skip to content

Commit

Permalink
Merge pull request #4 from dmariogatto/dev-net6
Browse files Browse the repository at this point in the history
net6.0
  • Loading branch information
dmariogatto authored Jun 16, 2022
2 parents cee3cc6 + 149c5ab commit 384e57e
Show file tree
Hide file tree
Showing 42 changed files with 12,222 additions and 8,599 deletions.
22 changes: 20 additions & 2 deletions src/Cats.CertificateTransparency.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30711.63
# Visual Studio Version 17
VisualStudioVersion = 17.3.32519.111
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cats.CertificateTransparency", "Cats.CertificateTransparency\Cats.CertificateTransparency.csproj", "{E9314C8B-7CA6-4295-9FB3-0BBB22C9455D}"
EndProject
Expand All @@ -24,6 +24,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests\Tests.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.Data", "Tests\Tests.Data\Tests.Data.csproj", "{28ED2DC4-22B1-456E-9C23-2882DC5508C4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Samples.Droid.net6", "Samples\Samples.Droid.net6\Samples.Droid.net6.csproj", "{C86573DA-9227-462B-9267-34816FE23908}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.Droid.net6", "Tests\Tests.Droid.net6\Tests.Droid.net6.csproj", "{E83305F6-E317-4095-93A1-80705C27C339}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -58,6 +62,18 @@ Global
{28ED2DC4-22B1-456E-9C23-2882DC5508C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{28ED2DC4-22B1-456E-9C23-2882DC5508C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{28ED2DC4-22B1-456E-9C23-2882DC5508C4}.Release|Any CPU.Build.0 = Release|Any CPU
{C86573DA-9227-462B-9267-34816FE23908}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C86573DA-9227-462B-9267-34816FE23908}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C86573DA-9227-462B-9267-34816FE23908}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{C86573DA-9227-462B-9267-34816FE23908}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C86573DA-9227-462B-9267-34816FE23908}.Release|Any CPU.Build.0 = Release|Any CPU
{C86573DA-9227-462B-9267-34816FE23908}.Release|Any CPU.Deploy.0 = Release|Any CPU
{E83305F6-E317-4095-93A1-80705C27C339}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E83305F6-E317-4095-93A1-80705C27C339}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E83305F6-E317-4095-93A1-80705C27C339}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{E83305F6-E317-4095-93A1-80705C27C339}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E83305F6-E317-4095-93A1-80705C27C339}.Release|Any CPU.Build.0 = Release|Any CPU
{E83305F6-E317-4095-93A1-80705C27C339}.Release|Any CPU.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -68,6 +84,8 @@ Global
{18497B17-CD53-46DC-AC16-D3F1BD3178D7} = {EC994E11-0FEB-4EAA-B2F8-3A72A4317BBC}
{515FB7C4-F8AC-4D02-9978-D350A246F408} = {EC994E11-0FEB-4EAA-B2F8-3A72A4317BBC}
{28ED2DC4-22B1-456E-9C23-2882DC5508C4} = {EC994E11-0FEB-4EAA-B2F8-3A72A4317BBC}
{C86573DA-9227-462B-9267-34816FE23908} = {82221379-8EB9-4D51-96CE-30FCACF9CB70}
{E83305F6-E317-4095-93A1-80705C27C339} = {EC994E11-0FEB-4EAA-B2F8-3A72A4317BBC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {70BA6A45-D92F-4A03-BDE0-0D851B48A4A6}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="MSBuild.Sdk.Extras/2.1.2">
<Project Sdk="MSBuild.Sdk.Extras/3.0.44">

<PropertyGroup>
<TargetFrameworks>netstandard2.1;monoandroid10.0;</TargetFrameworks>
<TargetFrameworks>netstandard2.1;monoandroid10.0;net6.0;net6.0-android;</TargetFrameworks>
<LangVersion>latest</LangVersion>

<AssemblyName>Cats.CertificateTransparency</AssemblyName>
Expand All @@ -15,8 +15,8 @@
<Product>$(AssemblyName) ($(TargetFramework))</Product>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<AssemblyFileVersion>1.0.0.0</AssemblyFileVersion>
<Version>1.3.0</Version>
<PackageVersion>1.3.0</PackageVersion>
<Version>2.0.0</Version>
<PackageVersion>2.0.0</PackageVersion>
<Authors>dmariogatto</Authors>
<Owners>dmariogatto</Owners>
<NeutralLanguage>en</NeutralLanguage>
Expand All @@ -25,8 +25,8 @@
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryType>git</RepositoryType>
<PackageReleaseNotes>
- Updated dependencies
- Linker safe
- Added net6.0 and net6.0-android support
- [net6.0-android] `CatsAndroidClientHandler` has been deprecated and removed. Use `CatsAndroidMessageHandler` instead.
</PackageReleaseNotes>
</PropertyGroup>

Expand All @@ -35,6 +35,10 @@
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>

<PropertyGroup Condition="$(TargetFramework.EndsWith('-android'))">
<SupportedOSPlatformVersion>21</SupportedOSPlatformVersion>
</PropertyGroup>

<ItemGroup>
<None Include="../../logo.png">
<Pack>True</Pack>
Expand All @@ -58,7 +62,11 @@
<None Include="Platforms\**\*.*" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('monoandroid')) ">
<ItemGroup Condition="$(TargetFramework.EndsWith('-android')) ">
<Compile Include="Platforms\Android\**\*.cs" />
</ItemGroup>

<ItemGroup Condition="$(TargetFramework.StartsWith('monoandroid')) ">
<Reference Include="System.IO.Compression" />
<Reference Include="System.IO.Compression.FileSystem" />

Expand Down
36 changes: 29 additions & 7 deletions src/Cats.CertificateTransparency/Constants/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#if DEBUG
[assembly: InternalsVisibleTo("Tests")]
[assembly: InternalsVisibleTo("Tests.Droid")]
[assembly: InternalsVisibleTo("Tests.Droid.net6")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
#endif

Expand All @@ -12,15 +13,20 @@ namespace Cats.CertificateTransparency
public static class Constants
{
public const int BitsInByte = 8;
public const int BytesInLong = 8;

public const int ExtensionsMaxLength = (1 << 16) - 1;
public const int SignatureMaxLength = (1 << 16) - 1;
public const int KeyIdLength = 32;
public const int TimestampLength = 8;
public const int VersionLength = 1;
public const int LogEntryTypeLength = 2;
public const int CertificateMaxLength = (1 << 24) - 1;
public const int X509TbsSequenceIndex = 0;
public const int TbsSpkiSequenceIndex = 6;

public const int ExtensionsMaxValue = (1 << 16) - 1;
public const int SignatureMaxValue = (1 << 16) - 1;
public const int CertificateMaxValue = (1 << 24) - 1;

public const int KeyIdNumOfBytes = 32;
public const int TimestampNumOfBytes = 8;
public const int VersionNumOfBytes = 1;
public const int LogEntryTypeNumOfBytes = 2;

public const string PreCertificateSigningOid = "1.3.6.1.4.1.11129.2.4.4";
public const string PoisonOid = "1.3.6.1.4.1.11129.2.4.3";
public const string SctCertificateOid = "1.3.6.1.4.1.11129.2.4.2";
Expand All @@ -35,5 +41,21 @@ public static class Constants

public const string Sha256WithRsa = "SHA256withRSA";
public const string Sha256WithEcdsa = "SHA256withECDSA";

internal static int BytesToStoreValue(int value)
{
if (value < 0) throw new ArgumentOutOfRangeException(nameof(value), "Cannot be negative");

var numBytes = 0;
var local = value;

while (local > 0)
{
local >>= Constants.BitsInByte;
numBytes++;
}

return numBytes;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ internal static class SignedCertificateTimestampExtensions
{
internal static SctVerificationResult VerifySignature(this SignedCertificateTimestamp sct, Log logServer, IList<X509Certificate2> chain)
{
if (logServer == null || sct == null || chain?.Any() != true || logServer.LogId != sct.LogIdBase64)
if (logServer is null || sct is null || chain?.Any() != true || logServer.LogId != sct.LogIdBase64)
return SctVerificationResult.FailedVerification(sct.TimestampUtc, logServer?.LogId, "Invalid verification arguments");

var nowUtc = DateTime.UtcNow;
Expand Down Expand Up @@ -80,24 +80,27 @@ private static TbsCertificateStructure CreateTbsForVerification(X509Certificate2
{
if (preCertificate.Version < 3) throw new InvalidOperationException("PreCertificate version must be 3 or higher!");

var asn1Obj = Asn1Object.FromByteArray(preCertificate.GetTbsCertificateRaw());
var asn1Obj = preCertificate.GetTbsCertificateAsn1Object();
var tbsCert = TbsCertificateStructure.GetInstance(asn1Obj);
var hasX509AuthorityKeyIdentifier = tbsCert.Extensions.GetExtension(new DerObjectIdentifier(Constants.X509AuthorityKeyIdentifier)) != null;
var hasX509AuthorityKeyIdentifier = tbsCert.Extensions.GetExtension(new DerObjectIdentifier(Constants.X509AuthorityKeyIdentifier)) is not null;

if (hasX509AuthorityKeyIdentifier &&
issuerInformation.IssuedByPreCertificateSigningCert &&
issuerInformation.X509AuthorityKeyIdentifier == null)
issuerInformation.X509AuthorityKeyIdentifier is null)
{
throw new InvalidOperationException("PreCertificate was not signed by a PreCertificate signing cert");
}

var orderedExtensions = GetExtensionsWithoutPoisonAndSct(tbsCert.Extensions, issuerInformation.X509AuthorityKeyIdentifier);
var issuer = !string.IsNullOrEmpty(issuerInformation.Name)
? new X509Name(issuerInformation.Name)
: tbsCert.Issuer;
var orderedExtensions = GetExtensionsWithoutPoisonAndSct(tbsCert.Extensions, issuerInformation);

var generator = new V3TbsCertificateGenerator();

generator.SetSerialNumber(tbsCert.SerialNumber);
generator.SetSignature(tbsCert.Signature);
generator.SetIssuer(issuerInformation.Name ?? tbsCert.Issuer);
generator.SetIssuer(issuer);
generator.SetStartDate(tbsCert.StartDate);
generator.SetEndDate(tbsCert.EndDate);
generator.SetSubject(tbsCert.Subject);
Expand All @@ -114,17 +117,19 @@ private static TbsCertificateStructure CreateTbsForVerification(X509Certificate2
return generator.GenerateTbsCertificate();
}

private static Dictionary<DerObjectIdentifier, X509Extension> GetExtensionsWithoutPoisonAndSct(X509Extensions extensions, X509Extension replacementX509Authority)
private static Dictionary<DerObjectIdentifier, X509Extension> GetExtensionsWithoutPoisonAndSct(X509Extensions extensions, IssuerInformation issuerInformation)
{
var result = new Dictionary<DerObjectIdentifier, X509Extension>();

foreach (DerObjectIdentifier oid in extensions.GetExtensionOids())
{
if (oid.Id != Constants.PoisonOid && oid.Id != Constants.SctCertificateOid)
if (!oid.Id.Equals(Constants.PoisonOid, StringComparison.Ordinal) && !oid.Id.Equals(Constants.SctCertificateOid, StringComparison.Ordinal))
{
if (oid.Id == Constants.X509AuthorityKeyIdentifier && replacementX509Authority != null)
if (issuerInformation?.X509AuthorityKeyIdentifier is not null && oid.Id.Equals(Constants.X509AuthorityKeyIdentifier, StringComparison.Ordinal))
{
result.Add(oid, replacementX509Authority);
var critical = issuerInformation.X509AuthorityKeyIdentifier.Critical;
var asn1OctetString = Asn1Object.FromByteArray(issuerInformation.X509AuthorityKeyIdentifier.RawData) as DerOctetString;
result.Add(oid, new X509Extension(critical, asn1OctetString));
}
else
{
Expand Down Expand Up @@ -163,9 +168,9 @@ private static byte[] SerialiseSignedSctData(this SignedCertificateTimestamp sct

SerialiseCommonFields(bw, sct);

bw.WriteLong(0, Constants.LogEntryTypeLength); // X509 Entry
bw.WriteVariableLength(certificate.RawData, Constants.CertificateMaxLength);
bw.WriteVariableLength(sct.Extensions, Constants.ExtensionsMaxLength);
bw.WriteLong(0, Constants.LogEntryTypeNumOfBytes); // X509 Entry
bw.WriteVariableLength(certificate.RawData, Constants.CertificateMaxValue);
bw.WriteVariableLength(sct.Extensions, Constants.ExtensionsMaxValue);

return ms.ToArray();
}
Expand All @@ -177,10 +182,10 @@ private static byte[] SerialiseSignedSctDataForPreCertificate(this SignedCertifi

SerialiseCommonFields(bw, sct);

bw.WriteLong(1, Constants.LogEntryTypeLength); // PerCert Entry
bw.WriteLong(1, Constants.LogEntryTypeNumOfBytes); // PerCert Entry
bw.Write(issuerKeyHash);
bw.WriteVariableLength(preCert, Constants.CertificateMaxLength);
bw.WriteVariableLength(sct.Extensions, Constants.ExtensionsMaxLength);
bw.WriteVariableLength(preCert, Constants.CertificateMaxValue);
bw.WriteVariableLength(sct.Extensions, Constants.ExtensionsMaxValue);

return ms.ToArray();
}
Expand All @@ -189,9 +194,9 @@ private static void SerialiseCommonFields(BinaryWriter bw, SignedCertificateTime
{
if (sct.SctVersion != SctVersion.V1) throw new InvalidOperationException("Can only serialise SCT v1!");

bw.WriteLong((long)sct.SctVersion, Constants.VersionLength);
bw.WriteLong((long)sct.SctVersion, Constants.VersionNumOfBytes);
bw.WriteLong(0, 1); // Certificate Timestamp
bw.WriteLong(sct.TimestampMs, Constants.TimestampLength);
bw.WriteLong(sct.TimestampMs, Constants.TimestampNumOfBytes);
}

private static (string oid, CtSignatureAlgorithm sigAlg) GetKeyAlgorithm(byte[] keyBytes)
Expand Down
37 changes: 37 additions & 0 deletions src/Cats.CertificateTransparency/Extensions/SpanExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.IO;

namespace Cats.CertificateTransparency.Extensions
{
internal static class SpanExtensions
{
internal static long ReadLong(this Span<byte> span, int bytesToRead, ref int position)
{
if (bytesToRead > Constants.BytesInLong)
throw new ArgumentOutOfRangeException(nameof(bytesToRead), $"Cannot read long of length {bytesToRead} bytes");

var result = 0L;

for (var i = 0; i < bytesToRead; i++)
{
var readVal = span[position++];
result = (result << Constants.BitsInByte) | readVal;
}

return result;
}

internal static Span<byte> ReadVariableLength(this Span<byte> span, int maxDataValue, ref int position)
{
var bytesForDataLength = Constants.BytesToStoreValue(maxDataValue);
var dataLength = ReadLong(span, bytesForDataLength, ref position);

var data = span.Slice(position, (int)dataLength);
position += data.Length;

if (data.Length != dataLength) throw new IOException($"Incomplete data. Expected {dataLength} bytes, got {span.Length}");

return data;
}
}
}
24 changes: 4 additions & 20 deletions src/Cats.CertificateTransparency/Extensions/StreamExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ internal static class StreamExtensions
{
internal static long ReadLong(this Stream stream, int numberOfBytes)
{
if (numberOfBytes > Constants.BitsInByte)
if (numberOfBytes > Constants.BytesInLong)
throw new ArgumentOutOfRangeException(nameof(numberOfBytes), $"Cannot read long of length {numberOfBytes} bytes");

var result = 0L;
Expand All @@ -22,9 +22,9 @@ internal static long ReadLong(this Stream stream, int numberOfBytes)
return result;
}

internal static byte[] ReadVariableLength(this Stream stream, int maxDataLength)
internal static byte[] ReadVariableLength(this Stream stream, int maxDataValue)
{
var bytesForDataLength = BytesToStoreValue(maxDataLength);
var bytesForDataLength = Constants.BytesToStoreValue(maxDataValue);
var dataLength = ReadLong(stream, bytesForDataLength);

var data = new byte[dataLength];
Expand Down Expand Up @@ -55,25 +55,9 @@ internal static void WriteVariableLength(this BinaryWriter writer, byte[] data,
{
if (data.Length > maxDataLength) throw new ArgumentOutOfRangeException($"Length {data.Length} is greater than max data length {maxDataLength}");

var bytesForDataLength = BytesToStoreValue(maxDataLength);
var bytesForDataLength = Constants.BytesToStoreValue(maxDataLength);
writer.WriteLong(data.Length, bytesForDataLength);
writer.Write(data, 0, data.Length);
}

private static int BytesToStoreValue(int value)
{
if (value < 0) throw new ArgumentOutOfRangeException(nameof(value), "Cannot be negative");

var numBytes = 0;
var local = value;

while (local > 0)
{
local >>= Constants.BitsInByte;
numBytes++;
}

return numBytes;
}
}
}
Loading

0 comments on commit 384e57e

Please sign in to comment.