private static unsafe TstInfo Decode(byte[] rawData) { var really = new byte[rawData.Length]; fixed(byte *pbData = rawData) { var decodedPtr = IntPtr.Zero; var cbStruct = 0; try { if (!Rfc3161TimestampWin32.CryptDecodeObjectEx( Rfc3161TimestampWin32.CryptEncodingTypes.X509_ASN_ENCODING, Rfc3161TimestampWin32.TIMESTAMP_INFO, (IntPtr)pbData, rawData.Length, Rfc3161TimestampWin32.CryptDecodeObjectFlags.CRYPT_DECODE_ALLOC_FLAG | Rfc3161TimestampWin32.CryptDecodeObjectFlags.CRYPT_DECODE_NOCOPY_FLAG | Rfc3161TimestampWin32.CryptDecodeObjectFlags.CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG, IntPtr.Zero, (IntPtr)(&decodedPtr), ref cbStruct)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } var tstInfo = ReadTstInfo(decodedPtr); //fixed (byte* pbReally = really) { uint cbReally = 0; var letThemEncodeIt = IntPtr.Zero; if (!Rfc3161TimestampWin32.CryptEncodeObjectEx( Rfc3161TimestampWin32.CryptEncodingTypes.X509_ASN_ENCODING, Rfc3161TimestampWin32.TIMESTAMP_INFO, decodedPtr, Rfc3161TimestampWin32.CryptEncodeObjectFlags.CRYPT_ENCODE_ALLOC_FLAG, IntPtr.Zero, (IntPtr)(&letThemEncodeIt), ref cbReally)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } really = new byte[cbReally]; Marshal.Copy(letThemEncodeIt, really, 0, (int)cbReally); } return(tstInfo); } finally { if (decodedPtr != IntPtr.Zero) { Rfc3161TimestampWin32.LocalFree(decodedPtr); } } } }
private static unsafe byte[] Encode(TstInfo tstInfo) { var algOid = tstInfo.HashAlgorithmId.Value; var policyOidBytes = new byte[tstInfo.PolicyId.Length + 1]; var algOidBytes = new byte[algOid.Length + 1]; var serialNumberBigEndian = tstInfo.SerialNumber; var serialNumberLittleEndian = new byte[serialNumberBigEndian.Length]; for (var i = 0; i < serialNumberLittleEndian.Length; i++) { serialNumberLittleEndian[i] = serialNumberBigEndian[serialNumberBigEndian.Length - i - 1]; } var filetime = tstInfo.Timestamp.ToFileTime(); fixed(byte *pbPolicyOid = policyOidBytes) fixed(char *pszPolicyOid = tstInfo.PolicyId) fixed(byte *pbHashedMessage = tstInfo.HashedMessage) fixed(byte *pbSerialNumber = serialNumberLittleEndian) fixed(char *pszAlgOid = algOid) fixed(byte *pbAlgOid = algOidBytes) fixed(byte *pbNonce = tstInfo.Nonce) fixed(byte *pbTsaName = tstInfo.TsaName) { Encoding.ASCII.GetBytes(pszPolicyOid, tstInfo.PolicyId.Length, pbPolicyOid, policyOidBytes.Length); Encoding.ASCII.GetBytes(pszAlgOid, algOid.Length, pbAlgOid, algOidBytes.Length); var info = new Rfc3161TimestampWin32.CRYPT_TIMESTAMP_INFO { dwVersion = tstInfo.Version, pszTSAPolicyId = (IntPtr)pbPolicyOid, fOrdering = tstInfo.IsOrdering, }; var accuracy = default(Rfc3161TimestampWin32.CRYPT_TIMESTAMP_ACCURACY); info.HashAlgorithm.pszOid = (IntPtr)pbAlgOid; info.HashedMessage.cbData = (uint)tstInfo.HashedMessage.Length; info.HashedMessage.pbData = (IntPtr)pbHashedMessage; info.SerialNumber.cbData = (uint)serialNumberLittleEndian.Length; info.SerialNumber.pbData = (IntPtr)pbSerialNumber; info.ftTime.dwLowDateTime = (int)(filetime & 0xFFFFFFFF); info.ftTime.dwHighDateTime = (int)(filetime >> 32); if (tstInfo.AccuracyInMicroseconds.HasValue) { var val = tstInfo.AccuracyInMicroseconds.Value; val = Math.DivRem(val, 1000, out var rem); accuracy.dwMicros = (int)rem; val = Math.DivRem(val, 1000, out rem); accuracy.dwMillis = (int)rem; if (val > int.MaxValue) { Debug.Fail($"accuracy value {tstInfo.AccuracyInMicroseconds.Value} had seconds component {val}, which should have been stopped"); throw new CryptographicException(); } accuracy.dwSeconds = (int)val; info.pvAccuracy = (IntPtr)(&accuracy); } if (tstInfo.Nonce != null) { info.Nonce.cbData = (uint)tstInfo.Nonce.Length; info.Nonce.pbData = (IntPtr)pbNonce; } if (tstInfo.TsaName != null) { info.Tsa.cbData = (uint)tstInfo.TsaName.Length; info.Tsa.pbData = (IntPtr)pbTsaName; } if (tstInfo.Extensions != null) { throw new NotImplementedException(); } var encodedDataPtr = IntPtr.Zero; uint cbEncoded = 0; try { if (!Rfc3161TimestampWin32.CryptEncodeObjectEx( Rfc3161TimestampWin32.CryptEncodingTypes.X509_ASN_ENCODING, Rfc3161TimestampWin32.TIMESTAMP_INFO, (IntPtr)(&info), Rfc3161TimestampWin32.CryptEncodeObjectFlags.CRYPT_ENCODE_ALLOC_FLAG, IntPtr.Zero, (IntPtr)(&encodedDataPtr), ref cbEncoded)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } var encoded = new byte[cbEncoded]; Marshal.Copy(encodedDataPtr, encoded, 0, (int)cbEncoded); return(encoded); } finally { if (encodedDataPtr != IntPtr.Zero) { Rfc3161TimestampWin32.LocalFree(encodedDataPtr); } } } }
private static unsafe byte[] Encode(DataType data) { IntPtr algorithmOidPtr = IntPtr.Zero; IntPtr policyOidPtr = IntPtr.Zero; IntPtr encodedDataPtr = IntPtr.Zero; try { algorithmOidPtr = Marshal.StringToHGlobalAnsi(data._hashAlgorithm.Value); policyOidPtr = Marshal.StringToHGlobalAnsi(data._requestedPolicyId?.Value); Rfc3161TimestampWin32.CRYPT_TIMESTAMP_REQUEST request = new Rfc3161TimestampWin32.CRYPT_TIMESTAMP_REQUEST { dwVersion = data._version, fCertReq = data._requestSignerCertificate, pszTSAPolicyId = policyOidPtr, }; request.HashAlgorithm.pszOid = algorithmOidPtr; request.HashedMessage.cbData = (uint)data._hash.Length; request.Nonce.cbData = (uint)(data._nonce?.Length ?? 0); fixed(byte *hashPtr = data._hash) fixed(byte *noncePtr = data._nonce) { request.HashedMessage.pbData = (IntPtr)hashPtr; request.Nonce.pbData = (IntPtr)noncePtr; uint cbEncoded = 0; if (!Rfc3161TimestampWin32.CryptEncodeObjectEx( Rfc3161TimestampWin32.CryptEncodingTypes.X509_ASN_ENCODING, Rfc3161TimestampWin32.TIMESTAMP_REQUEST, (IntPtr)(&request), Rfc3161TimestampWin32.CryptEncodeObjectFlags.CRYPT_ENCODE_ALLOC_FLAG, IntPtr.Zero, (IntPtr)(&encodedDataPtr), ref cbEncoded)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } byte[] encoded = new byte[cbEncoded]; Marshal.Copy(encodedDataPtr, encoded, 0, (int)cbEncoded); return(encoded); } } finally { if (algorithmOidPtr != IntPtr.Zero) { Marshal.FreeHGlobal(algorithmOidPtr); } if (policyOidPtr != IntPtr.Zero) { Marshal.FreeHGlobal(policyOidPtr); } if (encodedDataPtr != IntPtr.Zero) Rfc3161TimestampWin32.LocalFree(encodedDataPtr); } }