internal static ECParameters ExportNamedCurveParameters(CngKey key, bool includePrivateParameters) { byte[] ecBlob = ExportKeyBlob(key, 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 ECParameters ecParams = new ECParameters(); 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); } } } ecParams.Curve = ECCurve.CreateFromFriendlyName(key.GetCurveName()); return(ecParams); }
internal static void ExportParameters( CngKey key, bool includePrivateParameters, ref ECParameters ecparams) { string curveName = key.GetCurveName(); if (string.IsNullOrEmpty(curveName)) { byte[] fullKeyBlob = ECCng.ExportFullKeyBlob(key, includePrivateParameters); ECCng.ExportPrimeCurveParameters(ref ecparams, fullKeyBlob, includePrivateParameters); } else { byte[] keyBlob = ECCng.ExportKeyBlob(key, includePrivateParameters); ECCng.ExportNamedCurveParameters(ref ecparams, keyBlob, includePrivateParameters); ecparams.Curve = ECCurve.CreateFromFriendlyName(curveName); } }
/// <summary> /// Exports the key used by the ECC object into an <see cref="ECParameters"/> object. /// If the key was created as a named curve, the Curve property will contain named curve parameters /// otherwise it will contain explicit parameters. /// </summary> /// <exception cref="CryptographicException"> /// if there was an issue obtaining the curve values. /// </exception> /// <returns>The key and named curve parameters used by the ECC object.</returns> public override ECParameters ExportParameters() { using (CngKey key = Import()) { ECParameters ecparams = default; string? curveName = key.GetCurveName(out _); if (string.IsNullOrEmpty(curveName)) { byte[] fullKeyBlob = ECCng.ExportFullKeyBlob(key, includePrivateParameters: false); ECCng.ExportPrimeCurveParameters(ref ecparams, fullKeyBlob, includePrivateParameters: false); } else { byte[] keyBlob = ECCng.ExportKeyBlob(key, includePrivateParameters: false); ECCng.ExportNamedCurveParameters(ref ecparams, keyBlob, includePrivateParameters: false); ecparams.Curve = ECCurve.CreateFromFriendlyName(curveName); } return(ecparams); } }
internal static byte[] ExportKeyBlob( CngKey key, bool includePrivateParameters, out CngKeyBlobFormat format, out string?curveName) { curveName = key.GetCurveName(out _); bool forceGenericBlob = false; if (string.IsNullOrEmpty(curveName)) { // Normalize curveName to null. curveName = null; forceGenericBlob = true; format = includePrivateParameters ? CngKeyBlobFormat.EccFullPrivateBlob : CngKeyBlobFormat.EccFullPublicBlob; } else { format = includePrivateParameters ? CngKeyBlobFormat.EccPrivateBlob : CngKeyBlobFormat.EccPublicBlob; } byte[] blob = key.Export(format); // Importing a known NIST curve as explicit parameters NCryptExportKey may // cause it to export with the dwMagic of the known curve and a generic blob body. // This combination can't be re-imported. So correct the dwMagic value to allow it // to import. if (forceGenericBlob) { FixupGenericBlob(blob); } return(blob); }