/// <summary> /// Exports the key used by the RSA object into an RSAParameters object. /// </summary> public override RSAParameters ExportParameters(bool includePrivateParameters) { byte[] rsaBlob = Key.Export(includePrivateParameters ? s_rsaFullPrivateBlob : s_rsaPublicBlob); RSAParameters rsaParams = new RSAParameters(); // // We now have a buffer laid out as follows: // BCRYPT_RSAKEY_BLOB header // byte[cbPublicExp] publicExponent - Exponent // byte[cbModulus] modulus - Modulus // -- Private only -- // byte[cbPrime1] prime1 - P // byte[cbPrime2] prime2 - Q // byte[cbPrime1] exponent1 - DP // byte[cbPrime2] exponent2 - DQ // byte[cbPrime1] coefficient - InverseQ // byte[cbModulus] privateExponent - D // byte[] tempMagic = new byte[4]; tempMagic[0] = rsaBlob[0]; tempMagic[1] = rsaBlob[1]; tempMagic[2] = rsaBlob[2]; tempMagic[3] = rsaBlob[3]; KeyBlobMagicNumber magic = (KeyBlobMagicNumber)BitConverter.ToInt32(tempMagic, 0); // Check the magic value in the key blob header. If the blob does not have the required magic, // then throw a CryptographicException. CheckMagicValueOfKey(magic, includePrivateParameters); unsafe { // Fail-fast if a rogue provider gave us a blob that isn't even the size of the blob header. if (rsaBlob.Length < sizeof(BCRYPT_RSAKEY_BLOB)) throw ErrorCode.E_FAIL.ToCryptographicException(); fixed(byte *pRsaBlob = rsaBlob) { BCRYPT_RSAKEY_BLOB *pBcryptBlob = (BCRYPT_RSAKEY_BLOB *)pRsaBlob; int offset = sizeof(BCRYPT_RSAKEY_BLOB); // Read out the exponent rsaParams.Exponent = Consume(rsaBlob, ref offset, pBcryptBlob->cbPublicExp); rsaParams.Modulus = Consume(rsaBlob, ref offset, pBcryptBlob->cbModulus); if (includePrivateParameters) { rsaParams.P = Consume(rsaBlob, ref offset, pBcryptBlob->cbPrime1); rsaParams.Q = Consume(rsaBlob, ref offset, pBcryptBlob->cbPrime2); rsaParams.DP = Consume(rsaBlob, ref offset, pBcryptBlob->cbPrime1); rsaParams.DQ = Consume(rsaBlob, ref offset, pBcryptBlob->cbPrime2); rsaParams.InverseQ = Consume(rsaBlob, ref offset, pBcryptBlob->cbPrime1); rsaParams.D = Consume(rsaBlob, ref offset, pBcryptBlob->cbModulus); } } } return(rsaParams); }
private static void ExportParameters(ref RSAParameters rsaParams, byte[] rsaBlob, bool includePrivateParameters) { // // We now have a buffer laid out as follows: // BCRYPT_RSAKEY_BLOB header // byte[cbPublicExp] publicExponent - Exponent // byte[cbModulus] modulus - Modulus // -- Private only -- // byte[cbPrime1] prime1 - P // byte[cbPrime2] prime2 - Q // byte[cbPrime1] exponent1 - DP // byte[cbPrime2] exponent2 - DQ // byte[cbPrime1] coefficient - InverseQ // byte[cbModulus] privateExponent - D // KeyBlobMagicNumber magic = (KeyBlobMagicNumber)BitConverter.ToInt32(rsaBlob, 0); // Check the magic value in the key blob header. If the blob does not have the required magic, // then throw a CryptographicException. CheckMagicValueOfKey(magic, includePrivateParameters); unsafe { // Fail-fast if a rogue provider gave us a blob that isn't even the size of the blob header. if (rsaBlob.Length < sizeof(BCRYPT_RSAKEY_BLOB)) throw ErrorCode.E_FAIL.ToCryptographicException(); fixed(byte *pRsaBlob = &rsaBlob[0]) { BCRYPT_RSAKEY_BLOB *pBcryptBlob = (BCRYPT_RSAKEY_BLOB *)pRsaBlob; int offset = sizeof(BCRYPT_RSAKEY_BLOB); // Read out the exponent rsaParams.Exponent = Interop.BCrypt.Consume(rsaBlob, ref offset, pBcryptBlob->cbPublicExp); rsaParams.Modulus = Interop.BCrypt.Consume(rsaBlob, ref offset, pBcryptBlob->cbModulus); if (includePrivateParameters) { rsaParams.P = Interop.BCrypt.Consume(rsaBlob, ref offset, pBcryptBlob->cbPrime1); rsaParams.Q = Interop.BCrypt.Consume(rsaBlob, ref offset, pBcryptBlob->cbPrime2); rsaParams.DP = Interop.BCrypt.Consume(rsaBlob, ref offset, pBcryptBlob->cbPrime1); rsaParams.DQ = Interop.BCrypt.Consume(rsaBlob, ref offset, pBcryptBlob->cbPrime2); rsaParams.InverseQ = Interop.BCrypt.Consume(rsaBlob, ref offset, pBcryptBlob->cbPrime1); rsaParams.D = Interop.BCrypt.Consume(rsaBlob, ref offset, pBcryptBlob->cbModulus); } } } }
private static bool IsMagicValueOfKeyPrivate(KeyBlobMagicNumber magic) { switch (magic) { case KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_GENERIC_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_GENERIC_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_P256_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_P256_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_P384_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_P384_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_P521_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_P521_MAGIC: return(true); } return(false); }
/// <summary> /// This function checks the magic value in the key blob header /// </summary> /// <param name="includePrivateParameters">Private blob if true else public key blob</param> private static void CheckMagicValueOfKey(KeyBlobMagicNumber magic, bool includePrivateParameters) { if (includePrivateParameters) { if (!IsMagicValueOfKeyPrivate(magic)) { throw new CryptographicException(SR.Cryptography_NotValidPrivateKey); } } else { if (!IsMagicValueOfKeyPublic(magic)) { throw new CryptographicException(SR.Cryptography_NotValidPublicOrPrivateKey); } } }
private static bool IsMagicValueOfKeyPublic(KeyBlobMagicNumber magic) { switch (magic) { case KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_GENERIC_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_GENERIC_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_P256_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_P256_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_P384_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_P384_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_P521_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_P521_MAGIC: return(true); } // Private key magic is permissible too since the public key can be derived from the private key blob. return(IsMagicValueOfKeyPrivate(magic)); }
private static void ExportNamedCurveParameters( ref ECParameters ecParams, byte[] ecBlob, bool includePrivateParameters) { // We now have a buffer laid out as follows: // BCRYPT_ECCKEY_BLOB header // byte[cbKey] Q.X // byte[cbKey] Q.Y // -- Private only -- // byte[cbKey] D KeyBlobMagicNumber magic = (KeyBlobMagicNumber)BitConverter.ToInt32(ecBlob, 0); // Check the magic value in the key blob header. If the blob does not have the required magic, // then throw a CryptographicException. CheckMagicValueOfKey(magic, includePrivateParameters); unsafe { // Fail-fast if a rogue provider gave us a blob that isn't even the size of the blob header. if (ecBlob.Length < sizeof(BCRYPT_ECCKEY_BLOB)) throw ErrorCode.E_FAIL.ToCryptographicException(); fixed(byte *pEcBlob = ecBlob) { BCRYPT_ECCKEY_BLOB *pBcryptBlob = (BCRYPT_ECCKEY_BLOB *)pEcBlob; int offset = sizeof(BCRYPT_ECCKEY_BLOB); ecParams.Q = new ECPoint { X = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbKey), Y = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbKey) }; if (includePrivateParameters) { ecParams.D = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbKey); } } } }
/// <summary> /// This function checks the magic value in the key blob header /// </summary> /// <param name="magic">The expected magic number.</param> /// <param name="includePrivateParameters">Private blob if true else public key blob</param> private static void CheckMagicValueOfKey(KeyBlobMagicNumber magic, bool includePrivateParameters) { if (includePrivateParameters) { if (magic != KeyBlobMagicNumber.BCRYPT_RSAPRIVATE_MAGIC && magic != KeyBlobMagicNumber.BCRYPT_RSAFULLPRIVATE_MAGIC) { throw new CryptographicException(SR.Cryptography_NotValidPrivateKey); } } else { if (magic != KeyBlobMagicNumber.BCRYPT_RSAPUBLIC_MAGIC) { // Private key magic is permissible too since the public key can be derived from the private key blob. if (magic != KeyBlobMagicNumber.BCRYPT_RSAPRIVATE_MAGIC && magic != KeyBlobMagicNumber.BCRYPT_RSAFULLPRIVATE_MAGIC) { throw new CryptographicException(SR.Cryptography_NotValidPublicOrPrivateKey); } } } }
/// <summary> /// This function checks the magic value in the key blob header /// </summary> /// <param name="includePrivateParameters">Private blob if true else public key blob</param> private static void CheckMagicValueOfKey(KeyBlobMagicNumber magic, bool includePrivateParameters) { if (includePrivateParameters) { if (magic != KeyBlobMagicNumber.BCRYPT_RSAPRIVATE_MAGIC && magic != KeyBlobMagicNumber.BCRYPT_RSAFULLPRIVATE_MAGIC) { throw new CryptographicException(SR.Cryptography_NotValidPrivateKey); } } else { if (magic != KeyBlobMagicNumber.BCRYPT_RSAPUBLIC_MAGIC) { // Private key magic is permissible too since the public key can be derived from the private key blob. if (magic != KeyBlobMagicNumber.BCRYPT_RSAPRIVATE_MAGIC && magic != KeyBlobMagicNumber.BCRYPT_RSAFULLPRIVATE_MAGIC) { throw new CryptographicException(SR.Cryptography_NotValidPublicOrPrivateKey); } } } }
internal static void ExportPrimeCurveParameters(ref ECParameters ecParams, byte[] ecBlob, bool includePrivateParameters) { // We now have a buffer laid out as follows: // BCRYPT_ECCFULLKEY_BLOB header // byte[cbFieldLength] P // byte[cbFieldLength] A // byte[cbFieldLength] B // byte[cbFieldLength] G.X // byte[cbFieldLength] G.Y // byte[cbSubgroupOrder] Order (n) // byte[cbCofactor] Cofactor (h) // byte[cbSeed] Seed // byte[cbFieldLength] Q.X // byte[cbFieldLength] Q.Y // -- Private only -- // byte[cbSubgroupOrder] D KeyBlobMagicNumber magic = (KeyBlobMagicNumber)BitConverter.ToInt32(ecBlob, 0); // Check the magic value in the key blob header. If the blob does not have the required magic, // then throw a CryptographicException. CheckMagicValueOfKey(magic, includePrivateParameters); unsafe { // Fail-fast if a rogue provider gave us a blob that isn't even the size of the blob header. if (ecBlob.Length < sizeof(BCRYPT_ECCFULLKEY_BLOB)) throw ErrorCode.E_FAIL.ToCryptographicException(); fixed(byte *pEcBlob = &ecBlob[0]) { BCRYPT_ECCFULLKEY_BLOB *pBcryptBlob = (BCRYPT_ECCFULLKEY_BLOB *)pEcBlob; var primeCurve = new ECCurve(); primeCurve.CurveType = ConvertToCurveTypeEnum(pBcryptBlob->CurveType); primeCurve.Hash = GetHashAlgorithmName(pBcryptBlob->CurveGenerationAlgId); int offset = sizeof(BCRYPT_ECCFULLKEY_BLOB); primeCurve.Prime = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength); primeCurve.A = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength); primeCurve.B = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength); primeCurve.G = new ECPoint() { X = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength), Y = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength), }; primeCurve.Order = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbSubgroupOrder); primeCurve.Cofactor = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbCofactor); // Optional parameters primeCurve.Seed = pBcryptBlob->cbSeed == 0 ? null : Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbSeed); ecParams.Q = new ECPoint { X = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength), Y = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength) }; if (includePrivateParameters) { ecParams.D = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbSubgroupOrder); } ecParams.Curve = primeCurve; } } }
private static bool IsMagicValueOfKeyPublic(KeyBlobMagicNumber magic) { switch (magic) { case KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_GENERIC_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_GENERIC_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_P256_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_P256_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_P384_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_P384_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_P521_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_P521_MAGIC: return true; } // Private key magic is permissible too since the public key can be derived from the private key blob. return IsMagicValueOfKeyPrivate(magic); }
private static bool IsMagicValueOfKeyPrivate(KeyBlobMagicNumber magic) { switch (magic) { case KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_GENERIC_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_GENERIC_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_P256_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_P256_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_P384_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_P384_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_P521_MAGIC: case KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_P521_MAGIC: return true; } return false; }