示例#1
0
        public byte[] GetPrivateKeyBlob(IntPtr context, KeyDerivation derive)
        {
            bool result, shouldFree = false;

            NativeMethods.KeySpec addInfo = 0;

            IntPtr hProv = IntPtr.Zero, hExportKey = IntPtr.Zero,
                   phSessionKey = IntPtr.Zero, userKey = IntPtr.Zero;

            try {
                result = NativeMethods.CryptAcquireCertificatePrivateKey(context, 0, IntPtr.Zero, ref hProv, ref addInfo, ref shouldFree);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                result = NativeMethods.CryptGetUserKey(hProv, (uint)addInfo, ref userKey);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                CheckPermission(userKey);

                result = NativeMethods.CryptGenKey(hProv, EphemAlgId, 0, out phSessionKey);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                uint dhOIDsz = 50;
                var  dhOID   = new byte[dhOIDsz];
                result = NativeMethods.CryptGetKeyParam(phSessionKey, NativeMethods.KP_DHOID, dhOID, ref dhOIDsz, 0);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
                dhOID = dhOID.Take((int)dhOIDsz - 1).ToArray();
                var dhOIDstr = Encoding.ASCII.GetString(dhOID);

                uint hashOIDsz = 50;
                var  hashOID   = new byte[hashOIDsz];
                result = NativeMethods.CryptGetKeyParam(phSessionKey, NativeMethods.KP_HASHOID, hashOID, ref hashOIDsz, 0);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
                hashOID = hashOID.Take((int)hashOIDsz - 1).ToArray();
                var hashOIDstr = Encoding.ASCII.GetString(hashOID);

                uint pbdatalen = 0;
                result = NativeMethods.CryptExportKey(phSessionKey, IntPtr.Zero, NativeMethods.PUBLICKEYBLOB, 0, null, ref pbdatalen);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                SessionKey = new byte[pbdatalen];
                result     = NativeMethods.CryptExportKey(phSessionKey, IntPtr.Zero, NativeMethods.PUBLICKEYBLOB, 0, SessionKey, ref pbdatalen);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                var blob = new CRYPT_PUBLICKEYBLOB {
                    reserved = 0,
                    bType    = 6,
                    aiKeyAlg = (uint)KeyAlgId,
                    bVersion = 0x20,
                    Magic    = NativeMethods.GR3410_1_MAGIC,
                    BitLen   = PublicKeyLength
                };

                var dhOid   = new DerObjectIdentifier(dhOIDstr);
                var hashOid = new DerObjectIdentifier(hashOIDstr);
                var seq     = new DerSequence(dhOid, hashOid);

                var keyData = seq.GetDerEncoded();
                Array.Resize(ref keyData, 24);

                blob.KeyData1 = BitConverter.ToUInt64(keyData, 0);
                blob.KeyData2 = BitConverter.ToUInt64(keyData, 8);
                blob.KeyData3 = BitConverter.ToUInt64(keyData, 16);

                var blobData = blob.GetBytes();
                var pbdata2  = new byte[BlobLength];
                for (int i = 0; i < KeyOffset; ++i)
                {
                    pbdata2[i] = blobData[i];
                }

                derive.Init(dhOid, hashOid);
                var genkey = derive.GetPublicKeyBytes();

                for (int i = 0, j = KeyOffset; i < genkey.Length; ++i, ++j)
                {
                    pbdata2[j] = genkey[i];
                }

                result = NativeMethods.CryptImportKey(hProv, pbdata2, BlobLength, phSessionKey, 0, ref hExportKey);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                result = NativeMethods.CryptSetKeyParam(hExportKey, (int)NativeMethods.KP_ALGID, BitConverter.GetBytes((uint)ExportAlgId), 0);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                uint pkSize = 0;
                result = NativeMethods.CryptExportKey(userKey, hExportKey, NativeMethods.PRIVATEKEYBLOB, 0, null, ref pkSize);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                var ret = new byte[pkSize];
                result = NativeMethods.CryptExportKey(userKey, hExportKey, NativeMethods.PRIVATEKEYBLOB, 0, ret, ref pkSize);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                return(ret);
            } catch (Win32Exception e) {
                throw new CryptographicException(e.Message, e);
            } finally {
                if (shouldFree)
                {
                    NativeMethods.CryptReleaseContext(hProv, 0);
                }

                if (hExportKey != IntPtr.Zero)
                {
                    NativeMethods.CryptDestroyKey(hExportKey);
                }

                if (phSessionKey != IntPtr.Zero)
                {
                    NativeMethods.CryptDestroyKey(phSessionKey);
                }

                if (userKey != IntPtr.Zero)
                {
                    NativeMethods.CryptDestroyKey(userKey);
                }
            }
        }