示例#1
0
        internal static byte[] GetPrimeCurveBlob(ref ECParameters parameters, bool ecdh)
        {
            Debug.Assert(parameters.Curve.IsPrime);

            bool    includePrivateParameters = (parameters.D != null);
            ECCurve curve = parameters.Curve;

            byte[] blob;
            unsafe
            {
                // We need to build a key blob structured 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
                //     -- Only if "includePrivateParameters" is true --
                //     byte[cbSubgroupOrder]        D

                int blobSize = sizeof(BCRYPT_ECCFULLKEY_BLOB) +
                               curve.Prime.Length +
                               curve.A.Length +
                               curve.B.Length +
                               curve.G.X.Length +
                               curve.G.Y.Length +
                               curve.Order.Length +
                               curve.Cofactor.Length +
                               (curve.Seed == null ? 0 : curve.Seed.Length) +
                               parameters.Q.X.Length +
                               parameters.Q.Y.Length;

                if (includePrivateParameters)
                {
                    blobSize += parameters.D.Length;
                }

                blob = new byte[blobSize];
                fixed(byte *pBlob = &blob[0])
                {
                    // Build the header
                    BCRYPT_ECCFULLKEY_BLOB *pBcryptBlob = (BCRYPT_ECCFULLKEY_BLOB *)pBlob;

                    pBcryptBlob->Version = 1; // No constant for this found in bcrypt.h
                    pBcryptBlob->Magic   = includePrivateParameters ?
                                           (ecdh ? KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_GENERIC_MAGIC : KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_GENERIC_MAGIC) :
                                           (ecdh ? KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_GENERIC_MAGIC : KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_GENERIC_MAGIC);
                    pBcryptBlob->cbCofactor           = curve.Cofactor.Length;
                    pBcryptBlob->cbFieldLength        = parameters.Q.X.Length;
                    pBcryptBlob->cbSeed               = curve.Seed == null ? 0 : curve.Seed.Length;
                    pBcryptBlob->cbSubgroupOrder      = curve.Order.Length;
                    pBcryptBlob->CurveGenerationAlgId = GetHashAlgorithmId(curve.Hash);
                    pBcryptBlob->CurveType            = ConvertToCurveTypeEnum(curve.CurveType);

                    // Emit the blob
                    int offset = sizeof(BCRYPT_ECCFULLKEY_BLOB);

                    Interop.BCrypt.Emit(blob, ref offset, curve.Prime);
                    Interop.BCrypt.Emit(blob, ref offset, curve.A);
                    Interop.BCrypt.Emit(blob, ref offset, curve.B);
                    Interop.BCrypt.Emit(blob, ref offset, curve.G.X);
                    Interop.BCrypt.Emit(blob, ref offset, curve.G.Y);
                    Interop.BCrypt.Emit(blob, ref offset, curve.Order);
                    Interop.BCrypt.Emit(blob, ref offset, curve.Cofactor);
                    if (curve.Seed != null)
                    {
                        Interop.BCrypt.Emit(blob, ref offset, curve.Seed);
                    }
                    Interop.BCrypt.Emit(blob, ref offset, parameters.Q.X);
                    Interop.BCrypt.Emit(blob, ref offset, parameters.Q.Y);
                    if (includePrivateParameters)
                    {
                        Interop.BCrypt.Emit(blob, ref offset, parameters.D);
                    }

                    // We better have computed the right allocation size above!
                    Debug.Assert(offset == blobSize, "offset == blobSize");
                }

                return(blob);
            }
        }
示例#2
0
        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;
                }
            }
        }