public static extern bool CryptEncodeObjectEx ( [param: In, MarshalAs(UnmanagedType.U4)] EncodingType dwCertEncodingType, [param: In, MarshalAs(UnmanagedType.SysInt)] IntPtr lpszStructType, [param: In, MarshalAs(UnmanagedType.Struct)] ref CERT_PUBLIC_KEY_INFO pvStructInfo, [param: In, MarshalAs(UnmanagedType.U4)] uint dwFlags, [param: In, MarshalAs(UnmanagedType.SysInt)] IntPtr pEncodePara, [param: Out] out LocalBufferSafeHandle pvEncoded, [param: In, Out, MarshalAs(UnmanagedType.U4)] ref uint pcbEncoded );
public static string BuildHashForPublicKey(X509Certificate2 certificate, HashAlgorithm algorithm) { var PUBLIC_KEY_INFO_TYPE = new IntPtr(8); IntPtr publicKeyParametersBuffer = IntPtr.Zero, publicKeyBuffer = IntPtr.Zero, encodingBuffer = IntPtr.Zero; try { var publicKey = certificate.GetPublicKey(); publicKeyParametersBuffer = Marshal.AllocCoTaskMem(certificate.PublicKey.EncodedParameters.RawData.Length); publicKeyBuffer = Marshal.AllocCoTaskMem(publicKey.Length); Marshal.Copy(certificate.PublicKey.EncodedParameters.RawData, 0, publicKeyParametersBuffer, certificate.PublicKey.EncodedParameters.RawData.Length); Marshal.Copy(publicKey, 0, publicKeyBuffer, publicKey.Length); var publicKeyInfo = new CERT_PUBLIC_KEY_INFO(); publicKeyInfo.Algorithm = new CRYPT_ALGORITHM_IDENTIFIER(); publicKeyInfo.PublicKey = new CRYPT_BIT_BLOB(); publicKeyInfo.Algorithm.pszObjId = certificate.PublicKey.EncodedKeyValue.Oid.Value; publicKeyInfo.Algorithm.Parameters = new CRYPT_OBJID_BLOB(); publicKeyInfo.PublicKey.cbData = (uint)publicKey.Length; publicKeyInfo.PublicKey.cUnusedBits = 0; publicKeyInfo.PublicKey.pbData = publicKeyBuffer; publicKeyInfo.Algorithm.Parameters.cbData = (uint)certificate.PublicKey.EncodedParameters.RawData.Length; publicKeyInfo.Algorithm.Parameters.pbData = publicKeyParametersBuffer; uint size = 0; if (Crypto32.CryptEncodeObject(1, PUBLIC_KEY_INFO_TYPE, publicKeyInfo, IntPtr.Zero, ref size)) { encodingBuffer = Marshal.AllocCoTaskMem((int)size); if (Crypto32.CryptEncodeObject(1, PUBLIC_KEY_INFO_TYPE, publicKeyInfo, encodingBuffer, ref size)) { var encoded = new byte[size]; Marshal.Copy(encodingBuffer, encoded, 0, encoded.Length); return Convert.ToBase64String(algorithm.ComputeHash(encoded)); } } } finally { Marshal.FreeCoTaskMem(publicKeyParametersBuffer); Marshal.FreeCoTaskMem(encodingBuffer); Marshal.FreeCoTaskMem(publicKeyBuffer); } return null; }
private unsafe static CtPublicKey FromWin32Structure(CERT_PUBLIC_KEY_INFO spki) { CtPublicKeyType type; var parameters = new byte[spki.Algorithm.Parameters.cbData]; if (spki.Algorithm.Parameters.cbData > 0) { Marshal.Copy(spki.Algorithm.Parameters.pbData, parameters, 0, parameters.Length); } switch (spki.Algorithm.pszObjId) { case KnownOids.X509Algorithms.RSA: if (parameters.Length == 0 || IsAsnNull(parameters)) type = CtPublicKeyType.RSA_PKCS15; else goto default; break; case KnownOids.X509Algorithms.Ecc: var curve = OidParser.ReadFromBytes(parameters); if (curve?.Value == KnownOids.EccCurves.EcdsaP256) type = CtPublicKeyType.ECDSA_P256; else goto default; break; default: return null; } if (spki.PublicKey.cbData == 0) { return null; } var publicKey = new byte[spki.PublicKey.cbData]; Marshal.Copy(new IntPtr(spki.PublicKey.pbData), publicKey, 0, publicKey.Length); return new CtPublicKey { KeyType = type, Key = publicKey }; }