| File: Signing\Timestamp\Rfc3161TimestampTokenInfo.cs | Web Access |
| Project: src\nuget-client\src\NuGet.Core\NuGet.Packaging\NuGet.Packaging.csproj (NuGet.Packaging) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Security.Cryptography; #if IS_DESKTOP using System; using System.Linq; using System.Runtime.InteropServices; using System.Security.Cryptography.Pkcs; using System.Security.Cryptography.X509Certificates; #endif namespace NuGet.Packaging.Signing { /// <summary> /// Represents an RFC3161 TSTInfo. /// This class should be removed once we can reference it throught the .NET Core framework. /// </summary> public sealed class Rfc3161TimestampTokenInfo : AsnEncodedData { #if IS_DESKTOP public const string TimestampTokenInfoId = "1.2.840.113549.1.9.16.1.4"; private TstInfo? _decoded; private TstInfo Decoded { get { if (_decoded == null) _decoded = TstInfo.Read(RawData); return _decoded; } } public Rfc3161TimestampTokenInfo(byte[] timestampTokenInfo) : base(TimestampTokenInfoId, timestampTokenInfo) { } internal Rfc3161TimestampTokenInfo(IntPtr pTsContext) { var context = (Rfc3161TimestampWin32.CRYPT_TIMESTAMP_CONTEXT)Marshal.PtrToStructure(pTsContext, typeof(Rfc3161TimestampWin32.CRYPT_TIMESTAMP_CONTEXT)); byte[] encoded = new byte[context.cbEncoded]; Marshal.Copy(context.pbEncoded, encoded, 0, context.cbEncoded); var cms = new SignedCms(); cms.Decode(encoded); if (!string.Equals(cms.ContentInfo.ContentType.Value, Oids.TSTInfoContentType, StringComparison.Ordinal)) { throw new CryptographicException(Strings.InvalidAsn1); } RawData = cms.ContentInfo.Content; _decoded = TstInfo.Read(RawData); } public int Version => Decoded.Version; public string PolicyId => Decoded.Policy.Value; public Oid HashAlgorithmId { get { Oid value = Decoded.MessageImprint.HashAlgorithm.Algorithm; return new Oid(value.Value, value.FriendlyName); } } public byte[] GetMessageHash() { return (byte[])Decoded.MessageImprint.HashedMessage.Clone(); } public bool HasMessageHash(byte[] hash) { if (hash == null) return false; var value = Decoded.MessageImprint.HashedMessage; if (hash.Length != value.Length) { return false; } return value.SequenceEqual(hash); } /// <summary> /// Gets the serial number for the request in the big-endian byte order. /// </summary> public byte[] GetSerialNumber() { return (byte[])Decoded.SerialNumber.Clone(); } public DateTimeOffset Timestamp => Decoded.GenTime; public long? AccuracyInMicroseconds => Decoded.Accuracy?.GetTotalMicroseconds(); public bool IsOrdering => Decoded.Ordering; public byte[]? GetNonce() { var nonce = (byte[]?)Decoded.Nonce?.Clone(); if (nonce != null) { // Convert from big endian to little endian. Array.Reverse(nonce); } return nonce; } public byte[]? GetTimestampAuthorityName() { return (byte[]?)Decoded.Tsa?.Clone(); } public bool HasExtensions => Decoded.Extensions != null; public X509ExtensionCollection GetExtensions() { return ShallowCopy(Decoded.Extensions, preserveNull: false)!; } internal static X509ExtensionCollection? ShallowCopy(X509ExtensionCollection? existing, bool preserveNull) { if (preserveNull && existing == null) return null; var coll = new X509ExtensionCollection(); if (existing == null) return coll; foreach (var extn in existing) { coll.Add(extn); } return coll; } public override void CopyFrom(AsnEncodedData asnEncodedData) { _decoded = null; base.CopyFrom(asnEncodedData); } internal static byte[]? CopyFromNative(ref Rfc3161TimestampWin32.CRYPTOAPI_BLOB blob) { if (blob.cbData == 0) return null; byte[] answer = new byte[blob.cbData]; Marshal.Copy(blob.pbData, answer, 0, answer.Length); return answer; } #endif } }