예제 #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);
                }
            }
        }
예제 #2
0
        private static void ExportPrivateKey(SafeHandle context, byte[] genkey, out byte[] sessionKeyData, out byte[] privKeyData)
        {
            bool result, shouldFree = false;

            NativeMethods.KeySpec addInfo = 0;

            IntPtr provOrKey = IntPtr.Zero, hExportKey = IntPtr.Zero,
                   phSessionKey = IntPtr.Zero, provInfoPtr = IntPtr.Zero, userKey = IntPtr.Zero;

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

                uint pcbData = 0;
                result = NativeMethods.CertGetCertificateContextProperty(context, NativeMethods.CERT_KEY_PROV_INFO_PROP_ID, provInfoPtr, ref pcbData);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                provInfoPtr = Marshal.AllocHGlobal((int)pcbData);
                result      = NativeMethods.CertGetCertificateContextProperty(context, NativeMethods.CERT_KEY_PROV_INFO_PROP_ID, provInfoPtr, ref pcbData);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                var provInfo = (NativeMethods.CRYPT_KEY_PROV_INFO)Marshal.PtrToStructure(provInfoPtr, typeof(NativeMethods.CRYPT_KEY_PROV_INFO));
                result = NativeMethods.CryptGetUserKey(provOrKey, (uint)addInfo, ref userKey);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                CheckPermission(userKey);

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

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

                var blob = new CRYPT_PUBLICKEYBLOB
                {
                    reserved = 0,
                    bType    = 6,
                    aiKeyAlg = (uint)NativeMethods.ALG_ID.CALG_GR3410EL,
                    bVersion = 0x20,
                    Magic    = NativeMethods.GR3410_1_MAGIC,
                    BitLen   = 512,
                    // bASN1GostR3410_94_PublicKeyParameters
                    KeyData1 = 0x07061230,
                    KeyData2 = 0x0203852A,
                    KeyData3 = 0x06002402,
                    KeyData4 = 0x03852A07,
                    KeyData5 = 0x011E0202
                };

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

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

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

                // export wrapped key
                var alg = BitConverter.GetBytes((uint)NativeMethods.ALG_ID.CALG_PRO_EXPORT);
                result = NativeMethods.CryptSetKeyParam(hExportKey, (int)NativeMethods.KP_ALGID, alg, 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());
                }

                privKeyData = new byte[pkSize];
                result      = NativeMethods.CryptExportKey(userKey, hExportKey, NativeMethods.PRIVATEKEYBLOB, 0, privKeyData, ref pkSize);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            } catch (Win32Exception e) {
                throw new CryptographicException(e.Message, e);
            } finally {
                if (shouldFree)
                {
                    NativeMethods.CryptReleaseContext(provOrKey, 0);
                }

                if (provInfoPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(provInfoPtr);
                }

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

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

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