/// <summary> /// Returns the bytes that represent the symmetric key. /// </summary> /// <returns>An array of bytes.</returns> /// <exception cref="ObjectDisposedException">The SymmetricKey has been disposed.</exception> public byte[] ToBytes() { if (m_Handle == 0) { throw new ObjectDisposedException(this.GetType().FullName); } IntPtr pbSessionBlob = IntPtr.Zero; try { int dwSessionBlob = 0; if (SspiProvider.CryptExportKey(m_Handle, m_ExponentOfOne, SecurityConstants.SIMPLEBLOB, 0, IntPtr.Zero, ref dwSessionBlob) == 0) { throw new SecurityException("Cannot export key."); } pbSessionBlob = Marshal.AllocHGlobal(dwSessionBlob); if (SspiProvider.CryptExportKey(m_Handle, m_ExponentOfOne, SecurityConstants.SIMPLEBLOB, 0, pbSessionBlob, ref dwSessionBlob) == 0) { throw new SecurityException("Cannot export key."); } // Get session key size in bits int dwSize = 4; // sizeof(DWORD) int dwKeyMaterial = 0; if (SspiProvider.CryptGetKeyParam(m_Handle, SecurityConstants.KP_KEYLEN, ref dwKeyMaterial, ref dwSize, 0) == 0) { throw new SecurityException("Cannot retrieve key parameters."); } // Get the number of bytes and allocate buffer dwKeyMaterial /= 8; byte[] pbKeyMaterial = new byte[dwKeyMaterial]; // Skip the header int offset = 4 + IntPtr.Size; // sizeof(BLOBHEADER); offset += IntPtr.Size; // sizeof(ALG_ID); Marshal.Copy(new IntPtr(pbSessionBlob.ToInt64() + offset), pbKeyMaterial, 0, pbKeyMaterial.Length); // the key is reversed Array.Reverse(pbKeyMaterial); return(pbKeyMaterial); } finally { if (pbSessionBlob != IntPtr.Zero) { Marshal.FreeHGlobal(pbSessionBlob); } } }
/// <summary> /// Dynamically creates an exponent-of-one key. /// </summary> /// <returns>The handle of a exponent-of-one key.</returns> /// <exception cref="SecurityException">An error occurs while creating the key.</exception> private int CreateDynamicExponentOfOneKey() { int hPrivateKey = 0; int dwKeyBlob = 0; IntPtr keyblob = IntPtr.Zero; int dwBitLen; try { if (SspiProvider.CryptGenKey(m_Provider, new IntPtr(SecurityConstants.AT_KEYEXCHANGE), SecurityConstants.CRYPT_EXPORTABLE, ref hPrivateKey) == 0) { throw new SecurityException("Cannot generate key pair."); } // Export the private key, we'll convert it to a private // exponent of one key if (SspiProvider.CryptExportKey(hPrivateKey, 0, SecurityConstants.PRIVATEKEYBLOB, 0, IntPtr.Zero, ref dwKeyBlob) == 0) { throw new SecurityException("Cannot export generated key."); } keyblob = Marshal.AllocHGlobal(dwKeyBlob); if (SspiProvider.CryptExportKey(hPrivateKey, 0, SecurityConstants.PRIVATEKEYBLOB, 0, keyblob, ref dwKeyBlob) == 0) { throw new SecurityException("Cannot export generated key."); } SspiProvider.CryptDestroyKey(hPrivateKey); hPrivateKey = 0; // Get the bit length of the key dwBitLen = Marshal.ReadInt32(keyblob, 12); /* Modify the Exponent in Key BLOB format [Key BLOB format is documented in SDK] */ // Convert pubexp in rsapubkey to 1 int offset = 16; for (int i = 0; i < 4; i++) { if (i == 0) { Marshal.WriteByte(keyblob, offset, 1); } else { Marshal.WriteByte(keyblob, offset + i, 0); } } // Skip pubexp offset += 4; // Skip modulus, prime1, prime2 offset += dwBitLen / 8; offset += dwBitLen / 16; offset += dwBitLen / 16; // Convert exponent1 to 1 for (int i = 0; i < dwBitLen / 16; i++) { if (i == 0) { Marshal.WriteByte(keyblob, offset, 1); } else { Marshal.WriteByte(keyblob, offset + i, 0); } } // Skip exponent1 offset += dwBitLen / 16; // Convert exponent2 to 1 for (int i = 0; i < dwBitLen / 16; i++) { if (i == 0) { Marshal.WriteByte(keyblob, offset, 1); } else { Marshal.WriteByte(keyblob, offset + i, 0); } } // Skip exponent2, coefficient offset += dwBitLen / 16; offset += dwBitLen / 16; // Convert privateExponent to 1 for (int i = 0; i < dwBitLen / 8; i++) { if (i == 0) { Marshal.WriteByte(keyblob, offset, 1); } else { Marshal.WriteByte(keyblob, offset + i, 0); } } // Import the exponent-of-one private key. if (SspiProvider.CryptImportKey(m_Provider, keyblob, dwKeyBlob, 0, SecurityConstants.CRYPT_EXPORTABLE, ref hPrivateKey) == 0) { throw new SecurityException("Could not import modified key."); } } catch (Exception e) { if (hPrivateKey != 0) { SspiProvider.CryptDestroyKey(hPrivateKey); } throw e; } finally { if (keyblob != IntPtr.Zero) { Marshal.FreeHGlobal(keyblob); } } return(hPrivateKey); }