internal void ParsePublicBlob(byte[] blob, out string crv, out string x, out string y)
            {
                if (blob.Length < 2 * sizeof(int))
                {
                    throw new Exception("blob is definitely invalid");
                }

                int             offset         = 0;
                Func <int, int> increaseOffset = (size) => {
                    var oldOffset = offset;
                    offset += size;
                    return(oldOffset);
                };
                KeyBlobMagicNumber magic = (KeyBlobMagicNumber)BitConverter.ToUInt32(blob, increaseOffset(sizeof(uint)));
                int byteLength           = (int)BitConverter.ToUInt32(blob, increaseOffset(sizeof(uint)));

                if ((blob.Length - offset) != byteLength * 2)
                {
                    throw new Exception("expected equal length curve parameters to remain");
                }

                byte[] xBytes = new byte[byteLength];
                Buffer.BlockCopy(blob, increaseOffset(xBytes.Length), xBytes, 0, xBytes.Length);

                byte[] yBytes = new byte[byteLength];
                Buffer.BlockCopy(blob, increaseOffset(yBytes.Length), yBytes, 0, yBytes.Length);

                switch (magic)
                {
                case KeyBlobMagicNumber.ECDSA_PUBLIC_P256: {
                    crv = "P-256";
                    break;
                }

                case KeyBlobMagicNumber.ECDSA_PUBLIC_P384: {
                    crv = "P-384";
                    break;
                }

                case KeyBlobMagicNumber.ECDSA_PUBLIC_P521: {
                    crv = "P-521";
                    break;
                }

                default: {
                    throw new Exception("Unknown magic number " + magic);
                }
                }

                x = Base64UrlEncoder.Encode(xBytes);
                y = Base64UrlEncoder.Encode(yBytes);
            }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
 /// <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);
         }
     }
 }
Esempio n. 5
0
        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));
        }
Esempio n. 6
0
        /// <summary>
        ///     Map an algorithm identifier to a key size and magic number
        /// </summary>
        internal static void MapAlgorithmIdToMagic(string algorithm,
                                                   out KeyBlobMagicNumber algorithmMagic,
                                                   out int keySize)
        {
            //Contract.Requires(!String.IsNullOrEmpty(algorithm));

            switch (algorithm)
            {
            case AlgorithmName.ECDHP256:
                algorithmMagic = KeyBlobMagicNumber.ECDHPublicP256;
                keySize        = 256;
                break;

            case AlgorithmName.ECDHP384:
                algorithmMagic = KeyBlobMagicNumber.ECDHPublicP384;
                keySize        = 384;
                break;

            case AlgorithmName.ECDHP521:
                algorithmMagic = KeyBlobMagicNumber.ECDHPublicP521;
                keySize        = 521;
                break;

            case AlgorithmName.ECDsaP256:
                algorithmMagic = KeyBlobMagicNumber.ECDsaPublicP256;
                keySize        = 256;
                break;

            case AlgorithmName.ECDsaP384:
                algorithmMagic = KeyBlobMagicNumber.ECDsaPublicP384;
                keySize        = 384;
                break;

            case AlgorithmName.ECDsaP521:
                algorithmMagic = KeyBlobMagicNumber.ECDsaPublicP521;
                keySize        = 521;
                break;

            default:
                throw new ArgumentException("Cryptography_UnknownEllipticCurveAlgorithm");
                //throw new ArgumentException(SR.GetString(SR.Cryptography_UnknownEllipticCurveAlgorithm));
            }
        }
        internal static void MapAlgorithmIdToMagic(string algorithm, out KeyBlobMagicNumber algorithmMagic, out int keySize)
        {
            switch (algorithm)
            {
            case "ECDH_P256":
                algorithmMagic = KeyBlobMagicNumber.ECDHPublicP256;
                keySize        = 0x100;
                return;

            case "ECDH_P384":
                algorithmMagic = KeyBlobMagicNumber.ECDHPublicP384;
                keySize        = 0x180;
                return;

            case "ECDH_P521":
                algorithmMagic = KeyBlobMagicNumber.ECDHPublicP521;
                keySize        = 0x209;
                return;

            case "ECDSA_P256":
                algorithmMagic = KeyBlobMagicNumber.ECDsaPublicP256;
                keySize        = 0x100;
                return;

            case "ECDSA_P384":
                algorithmMagic = KeyBlobMagicNumber.ECDsaPublicP384;
                keySize        = 0x180;
                return;

            case "ECDSA_P521":
                algorithmMagic = KeyBlobMagicNumber.ECDsaPublicP521;
                keySize        = 0x209;
                return;
            }
            throw new ArgumentException(System.SR.GetString("Cryptography_UnknownEllipticCurveAlgorithm"));
        }
Esempio n. 8
0
        internal static ECParameters ExportPrimeCurveParameters(CngKey key, bool includePrivateParameters)
        {
            byte[] ecBlob = ExportFullKeyBlob(key, 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

            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_ECCFULLKEY_BLOB))
                    throw ErrorCode.E_FAIL.ToCryptographicException();

                fixed(byte *pEcBlob = ecBlob)
                {
                    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;
                    return(ecParams);
                }
            }
        }