/// <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_DSA_PRIVATE_MAGIC && magic != KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC_V2) { throw new CryptographicException(SR.Cryptography_NotValidPrivateKey); } } else { if (magic != KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC && magic != KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC_V2) { throw new CryptographicException(SR.Cryptography_NotValidPublicOrPrivateKey); } } }
public override DSAParameters ExportParameters(bool includePrivateParameters) { byte[] dsaBlob = ExportKeyBlob(includePrivateParameters); KeyBlobMagicNumber magic = (KeyBlobMagicNumber)BitConverter.ToInt32(dsaBlob, 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 { DSAParameters dsaParams = default; fixed(byte *pDsaBlob = dsaBlob) { int offset; if (magic == KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC || magic == KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC) { if (dsaBlob.Length < sizeof(BCRYPT_DSA_KEY_BLOB)) { throw ErrorCode.E_FAIL.ToCryptographicException(); } BCRYPT_DSA_KEY_BLOB *pBcryptBlob = (BCRYPT_DSA_KEY_BLOB *)pDsaBlob; // We now have a buffer laid out as follows: // BCRYPT_DSA_KEY_BLOB header // byte[cbKey] P // byte[cbKey] G // byte[cbKey] Y // -- Private only -- // byte[Sha1HashOutputSize] X offset = sizeof(KeyBlobMagicNumber) + sizeof(int); // skip Magic and cbKey // Read out a (V1) BCRYPT_DSA_KEY_BLOB structure. dsaParams.Counter = BinaryPrimitives.ReadInt32BigEndian(Interop.BCrypt.Consume(dsaBlob, ref offset, 4)); dsaParams.Seed = Interop.BCrypt.Consume(dsaBlob, ref offset, Sha1HashOutputSize); dsaParams.Q = Interop.BCrypt.Consume(dsaBlob, ref offset, Sha1HashOutputSize); Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB)}"); dsaParams.P = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey); dsaParams.G = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey); dsaParams.Y = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey); if (includePrivateParameters) { dsaParams.X = Interop.BCrypt.Consume(dsaBlob, ref offset, Sha1HashOutputSize); } } else { Debug.Assert(magic == KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC_V2 || magic == KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC_V2); if (dsaBlob.Length < sizeof(BCRYPT_DSA_KEY_BLOB_V2)) { throw ErrorCode.E_FAIL.ToCryptographicException(); } BCRYPT_DSA_KEY_BLOB_V2 *pBcryptBlob = (BCRYPT_DSA_KEY_BLOB_V2 *)pDsaBlob; // We now have a buffer laid out as follows: // BCRYPT_DSA_KEY_BLOB_V2 header // byte[cbSeedLength] Seed // byte[cbGroupSize] Q // byte[cbKey] P // byte[cbKey] G // byte[cbKey] Y // -- Private only -- // byte[cbGroupSize] X offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2) - 4; //skip to Count[4] // Read out a BCRYPT_DSA_KEY_BLOB_V2 structure. dsaParams.Counter = BinaryPrimitives.ReadInt32BigEndian(Interop.BCrypt.Consume(dsaBlob, ref offset, 4)); Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB_V2), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB_V2)}"); dsaParams.Seed = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbSeedLength); dsaParams.Q = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbGroupSize); dsaParams.P = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey); dsaParams.G = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey); dsaParams.Y = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey); if (includePrivateParameters) { dsaParams.X = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbGroupSize); } } // If no counter/seed information is present, normalize Counter and Seed to 0/null to maintain parity with the CAPI version of DSA. if (dsaParams.Counter == -1) { dsaParams.Counter = 0; dsaParams.Seed = null; } Debug.Assert(offset == dsaBlob.Length, $"Expected offset = dsaBlob.Length, got {offset} != {dsaBlob.Length}"); return(dsaParams); } } }
/// <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_DSA_PRIVATE_MAGIC && magic != KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC_V2) throw new CryptographicException(SR.Cryptography_NotValidPrivateKey); } else { if (magic != KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC && magic != KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC_V2) throw new CryptographicException(SR.Cryptography_NotValidPublicOrPrivateKey); } }