예제 #1
0
파일: RsaCng.cs 프로젝트: sigma-random/mono
        public override void ImportParameters(RSAParameters parameters)
        {
            if (parameters.Exponent == null || parameters.Modulus == null)
            {
                throw new ArgumentException(SR.GetString(SR.Cryptography_InvalidRsaParameters));
            }
            bool publicOnly = parameters.P == null || parameters.Q == null;

            //
            // We need to build a key blob structured as follows:
            //     BCRYPT_RSAKEY_BLOB   header
            //     byte[cbPublicExp]    publicExponent      - Exponent
            //     byte[cbModulus]      modulus             - Modulus
            //     -- Private only --
            //     byte[cbPrime1]       prime1              - P
            //     byte[cbPrime2]       prime2              - Q
            //

            int blobSize = Marshal.SizeOf(typeof(BCryptNative.BCRYPT_RSAKEY_BLOB)) +
                           parameters.Exponent.Length +
                           parameters.Modulus.Length;

            if (!publicOnly)
            {
                blobSize += parameters.P.Length +
                            parameters.Q.Length;
            }

            byte[] rsaBlob = new byte[blobSize];
            unsafe
            {
                fixed(byte *pRsaBlob = rsaBlob)
                {
                    // Build the header
                    BCryptNative.BCRYPT_RSAKEY_BLOB *pBcryptBlob = (BCryptNative.BCRYPT_RSAKEY_BLOB *)pRsaBlob;
                    pBcryptBlob->Magic = publicOnly ? BCryptNative.KeyBlobMagicNumber.RsaPublic :
                                         BCryptNative.KeyBlobMagicNumber.RsaPrivate;

                    pBcryptBlob->BitLength = parameters.Modulus.Length * 8;

                    pBcryptBlob->cbPublicExp = parameters.Exponent.Length;
                    pBcryptBlob->cbModulus   = parameters.Modulus.Length;

                    if (!publicOnly)
                    {
                        pBcryptBlob->cbPrime1 = parameters.P.Length;
                        pBcryptBlob->cbPrime2 = parameters.Q.Length;
                    }

                    int offset = Marshal.SizeOf(typeof(BCryptNative.BCRYPT_RSAKEY_BLOB));

                    // Copy the exponent
                    Buffer.BlockCopy(parameters.Exponent, 0, rsaBlob, offset, parameters.Exponent.Length);
                    offset += parameters.Exponent.Length;

                    // Copy the modulus
                    Buffer.BlockCopy(parameters.Modulus, 0, rsaBlob, offset, parameters.Modulus.Length);
                    offset += parameters.Modulus.Length;

                    if (!publicOnly)
                    {
                        // Copy P
                        Buffer.BlockCopy(parameters.P, 0, rsaBlob, offset, parameters.P.Length);
                        offset += parameters.P.Length;

                        // Copy Q
                        Buffer.BlockCopy(parameters.Q, 0, rsaBlob, offset, parameters.Q.Length);
                        offset += parameters.Q.Length;
                    }
                }
            }
            Key = CngKey.Import(rsaBlob, publicOnly ? s_rsaPublicBlob : s_rsaPrivateBlob);
        }
예제 #2
0
        /// <summary>
        ///     <para>
        ///         ImportParameters will replace the existing key that RSACng is working with by creating a
        ///         new CngKey for the parameters structure. If the parameters structure contains only an
        ///         exponent and modulus, then only a public key will be imported. If the parameters also
        ///         contain P and Q values, then a full key pair will be imported.
        ///     </para>
        /// </summary>
        /// <exception cref="ArgumentException">
        ///     if <paramref name="parameters" /> contains neither an exponent nor a modulus.
        /// </exception>
        /// <exception cref="CryptographicException">
        ///     if <paramref name="parameters" /> is not a valid RSA key or if <paramref name="parameters"
        ///     /> is a full key pair and the default KSP is used.
        /// </exception>
        public override void ImportParameters(RSAParameters parameters)
        {
            unsafe
            {
                if (parameters.Exponent == null || parameters.Modulus == null)
                {
                    throw new CryptographicException(SR.Cryptography_InvalidRsaParameters);
                }

                bool includePrivate;
                if (parameters.D == null)
                {
                    includePrivate = false;
                    if (parameters.P != null || parameters.DP != null || parameters.Q != null || parameters.DQ != null || parameters.InverseQ != null)
                    {
                        throw new CryptographicException(SR.Cryptography_InvalidRsaParameters);
                    }
                }
                else
                {
                    includePrivate = true;
                    if (parameters.P == null || parameters.DP == null || parameters.Q == null || parameters.DQ == null || parameters.InverseQ == null)
                    {
                        throw new CryptographicException(SR.Cryptography_InvalidRsaParameters);
                    }
                }

                //
                // We need to build a key blob structured as follows:
                //
                //     BCRYPT_RSAKEY_BLOB   header
                //     byte[cbPublicExp]    publicExponent      - Exponent
                //     byte[cbModulus]      modulus             - Modulus
                //     -- Only if "includePrivate" is true --
                //     byte[cbPrime1]       prime1              - P
                //     byte[cbPrime2]       prime2              - Q
                //     ------------------
                //

                int blobSize = sizeof(BCRYPT_RSAKEY_BLOB) +
                               parameters.Exponent.Length +
                               parameters.Modulus.Length;
                if (includePrivate)
                {
                    blobSize += parameters.P.Length +
                                parameters.Q.Length;
                }

                byte[] rsaBlob = new byte[blobSize];
                fixed(byte *pRsaBlob = rsaBlob)
                {
                    // Build the header
                    BCRYPT_RSAKEY_BLOB *pBcryptBlob = (BCRYPT_RSAKEY_BLOB *)pRsaBlob;

                    pBcryptBlob->Magic       = includePrivate ? KeyBlobMagicNumber.BCRYPT_RSAPRIVATE_MAGIC : KeyBlobMagicNumber.BCRYPT_RSAPUBLIC_MAGIC;
                    pBcryptBlob->BitLength   = parameters.Modulus.Length * 8;
                    pBcryptBlob->cbPublicExp = parameters.Exponent.Length;
                    pBcryptBlob->cbModulus   = parameters.Modulus.Length;

                    if (includePrivate)
                    {
                        pBcryptBlob->cbPrime1 = parameters.P.Length;
                        pBcryptBlob->cbPrime2 = parameters.Q.Length;
                    }

                    int offset = sizeof(BCRYPT_RSAKEY_BLOB);

                    Emit(rsaBlob, ref offset, parameters.Exponent);
                    Emit(rsaBlob, ref offset, parameters.Modulus);

                    if (includePrivate)
                    {
                        Emit(rsaBlob, ref offset, parameters.P);
                        Emit(rsaBlob, ref offset, parameters.Q);
                    }

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

                CngKeyBlobFormat blobFormat = includePrivate ? s_rsaPrivateBlob : s_rsaPublicBlob;

                CngKey newKey = CngKey.Import(rsaBlob, blobFormat);
                newKey.ExportPolicy |= CngExportPolicies.AllowPlaintextExport;

                Key = newKey;
            }
        }