Esempio n. 1
0
        private static void WriteDSSSeed(DSAParameters dsaParameters, BinaryWriter bw)
        {
            if (dsaParameters.Seed == null || dsaParameters.Seed.Length == 0)
            {
                bw.Write(0xFFFFFFFF); // counter

                // seed[20] needs to be all 0xFF
                for (int i = 0; i < 20; i += sizeof(uint))
                {
                    bw.Write(0xFFFFFFFF);
                }
            }
            else
            {
                bw.Write((int)dsaParameters.Counter);
                bw.WriteReversed(dsaParameters.Seed);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Helper for DsaCryptoServiceProvider.ImportParameters()
        /// </summary>
        internal static byte[] ToKeyBlob(this DSAParameters dsaParameters)
        {
            const int NTE_BAD_DATA = unchecked((int)CryptKeyError.NTE_BAD_DATA);

            // Validate the DSA structure first
            // P and Q are required. Q is a 160 bit divisor of P-1.
            if (dsaParameters.P == null || dsaParameters.P.Length == 0 || dsaParameters.Q == null || dsaParameters.Q.Length != DSS_Q_LEN)
                throw NTE_BAD_DATA.ToCryptographicException();

            // G is required. G is an element of Z_p
            if (dsaParameters.G == null || dsaParameters.G.Length != dsaParameters.P.Length)
                throw NTE_BAD_DATA.ToCryptographicException();

            // If J is present, it should be less than the size of P: J = (P-1) / Q
            // This is only a sanity check. Not doing it here is not really an issue as CAPI will fail.
            if (dsaParameters.J != null && dsaParameters.J.Length >= dsaParameters.P.Length)
                throw NTE_BAD_DATA.ToCryptographicException();

            // Y is present for V3 DSA key blobs, Y = g^j mod P
            if (dsaParameters.Y != null && dsaParameters.Y.Length != dsaParameters.P.Length)
                throw NTE_BAD_DATA.ToCryptographicException();

            // The seed is always a 20 byte array
            if (dsaParameters.Seed != null && dsaParameters.Seed.Length != 20)
                throw NTE_BAD_DATA.ToCryptographicException();

            bool isPrivate = (dsaParameters.X != null && dsaParameters.X.Length > 0);

            // The private key should be the same length as Q
            if (isPrivate && dsaParameters.X.Length != DSS_Q_LEN)
                throw NTE_BAD_DATA.ToCryptographicException();

            uint bitLenP = (uint)dsaParameters.P.Length * 8;
            uint bitLenJ = dsaParameters.J == null ? 0 : (uint)dsaParameters.J.Length * 8;

            using (var ms = new MemoryStream())
            using (var bw = new BinaryWriter(ms))
            {
                // Write out the BLOBHEADER
                bool isV3;
                WriteKeyBlobHeader(dsaParameters, bw, isPrivate, out isV3);

                // Write out the DSA key
                if (isV3)
                {
                    // We need to build a key blob (DSSPUBKEY_VER3 or DSSPRIVKEY_VER3) as follows:
                    //  DWORD           magic
                    //  DWORD           bitlenP
                    //  DWORD           bitlenQ
                    //  DWORD           bitlenJ
                    //  DWORD           bitlenX (if private)
                    //  DWORD           counter (DSSSEED)
                    //  BYTE[20]        seed (DSSSEED)
                    //  BYTE[lenP]      P
                    //  BYTE[lenQ]      Q
                    //  BYTE[lenP]      G
                    //  BYTE[lenJ]      J (optional)
                    //  BYTE[lenP]      Y
                    //  BYTE[lenX]      X (if private)

                    bw.Write((int)(isPrivate ? DSS_PRIV_MAGIC_VER3 : DSS_PUB_MAGIC_VER3));
                    bw.Write((uint)(bitLenP));
                    bw.Write((uint)(dsaParameters.Q.Length * 8));
                    bw.Write((uint)(bitLenJ));

                    if (isPrivate)
                    {
                        bw.Write((uint)dsaParameters.X.Length * 8);
                    }

                    WriteDSSSeed(dsaParameters, bw);

                    bw.WriteReversed(dsaParameters.P);
                    bw.WriteReversed(dsaParameters.Q);
                    bw.WriteReversed(dsaParameters.G);

                    if (bitLenJ != 0)
                    {
                        bw.WriteReversed(dsaParameters.J);
                    }

                    bw.WriteReversed(dsaParameters.Y);

                    if (isPrivate)
                    {
                        bw.WriteReversed(dsaParameters.X);
                    }
                }
                else
                {
                    // We need to build a key blob as follows:
                    //  DWORD           magic (DSSPUBKEY)
                    //  DWORD           bitlen (DSSPUBKEY)
                    //  BYTE[len]       P
                    //  BYTE[DSS_Q_LEN] Q
                    //  BYTE[len]       G
                    //  BYTE[20]        X (if private)
                    //  BYTE[len]       Y (if public)
                    //  DWORD           counter (DSSSEED)
                    //  BYTE[20]        seed (DSSSEED)

                    bw.Write((int)(isPrivate ? DSS_PRIVATE_MAGIC : DSS_MAGIC));
                    bw.Write((uint)(bitLenP));
                    bw.WriteReversed(dsaParameters.P);
                    bw.WriteReversed(dsaParameters.Q);
                    bw.WriteReversed(dsaParameters.G);

                    if (isPrivate)
                    {
                        bw.WriteReversed(dsaParameters.X);
                    }
                    else
                    {
                        bw.WriteReversed(dsaParameters.Y);
                    }

                    WriteDSSSeed(dsaParameters, bw);
                }

                bw.Flush();
                byte[] key = ms.ToArray();
                return key;
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Helper for RsaCryptoServiceProvider.ImportParameters()
        /// </summary>
        internal static byte[] ToKeyBlob(this RSAParameters rsaParameters, int algId)
        {
            // The original FCall this helper emulates supports other algId's - however, the only algid we need to support is CALG_RSA_KEYX. We will not
            // port the codepaths dealing with other algid's.
            if (algId != CapiHelper.CALG_RSA_KEYX)
                throw new PlatformNotSupportedException();

            const int NTE_BAD_DATA = unchecked((int)CryptKeyError.NTE_BAD_DATA);

            // Validate the RSA structure first.
            if (rsaParameters.Modulus == null)
                throw NTE_BAD_DATA.ToCryptographicException();

            if (rsaParameters.Exponent == null || rsaParameters.Exponent.Length > 4)
                throw NTE_BAD_DATA.ToCryptographicException();

            int modulusLength = rsaParameters.Modulus.Length;
            int halfModulusLength = (modulusLength + 1) / 2;

            // We assume that if P != null, then so are Q, DP, DQ, InverseQ and D
            if (rsaParameters.P != null)
            {
                if (rsaParameters.P.Length != halfModulusLength)
                    throw NTE_BAD_DATA.ToCryptographicException();

                if (rsaParameters.Q == null || rsaParameters.Q.Length != halfModulusLength)
                    throw NTE_BAD_DATA.ToCryptographicException();

                if (rsaParameters.DP == null || rsaParameters.DP.Length != halfModulusLength)
                    throw NTE_BAD_DATA.ToCryptographicException();

                if (rsaParameters.DQ == null || rsaParameters.DQ.Length != halfModulusLength)
                    throw NTE_BAD_DATA.ToCryptographicException();

                if (rsaParameters.InverseQ == null || rsaParameters.InverseQ.Length != halfModulusLength)
                    throw NTE_BAD_DATA.ToCryptographicException();

                if (rsaParameters.D == null || rsaParameters.D.Length != modulusLength)
                    throw NTE_BAD_DATA.ToCryptographicException();
            }

            bool isPrivate = (rsaParameters.P != null && rsaParameters.P.Length != 0);

            MemoryStream ms = new MemoryStream();
            BinaryWriter bw = new BinaryWriter(ms);

            // Write out the BLOBHEADER
            bw.Write((byte)(isPrivate ? PRIVATEKEYBLOB : PUBLICKEYBLOB));  // BLOBHEADER.bType
            bw.Write((byte)(BLOBHEADER_CURRENT_BVERSION));                 // BLOBHEADER.bVersion
            bw.Write((ushort)0);                                           // BLOBHEADER.wReserved
            bw.Write((uint)algId);                                         // BLOBHEADER.aiKeyAlg

            // Write the RSAPubKey header
            bw.Write((int)(isPrivate ? RSA_PRIV_MAGIC : RSA_PUB_MAGIC));   // RSAPubKey.magic
            bw.Write((uint)(modulusLength * 8));                           // RSAPubKey.bitLen

            uint expAsDword = 0;
            for (int i = 0; i < rsaParameters.Exponent.Length; i++)
            {
                expAsDword <<= 8;
                expAsDword |= rsaParameters.Exponent[i];
            }
            bw.Write((uint)expAsDword);                                    // RSAPubKey.pubExp

            bw.WriteReversed(rsaParameters.Modulus);                       // Copy over the modulus for both public and private

            if (isPrivate)
            {
                bw.WriteReversed(rsaParameters.P);
                bw.WriteReversed(rsaParameters.Q);
                bw.WriteReversed(rsaParameters.DP);
                bw.WriteReversed(rsaParameters.DQ);
                bw.WriteReversed(rsaParameters.InverseQ);
                bw.WriteReversed(rsaParameters.D);
            }

            bw.Flush();
            byte[] key = ms.ToArray();
            return key;
        }