Пример #1
0
        /// <summary>
        /// Sign
        /// </summary>
        /// <param name="privateKey">private key</param>
        /// <param name="data">data to be signed</param>
        /// <param name="signature">signature returned</param>
        /// <returns>true if the signing succeeded, otherwise false.</returns>
        public override bool Sign(byte[] privateKey, byte[] data, out byte[] signature)
        {
            // based on draft-irtf-cfrg-eddsa-08 "Edwards-curve Digital Signature Algorithm (EdDSA)"

            if (privateKey.Length != 32)
            {
                signature = null;
                return(false);
            }

            using (var sha512 = new SHA512CryptoServiceProvider()) {
                byte[] hash;
                hash = sha512.ComputeHash(privateKey);

                byte[] sdata = new byte[32];
                Buffer.BlockCopy(hash, 0, sdata, 0, 32);
                sdata[0]  &= (byte)((0xff << _c) & 0xff); // clear lower bits
                sdata[31] &= (byte)((1 << (_n % 8)) - 1); // clear higher bits
                sdata[31] |= (byte)(1 << (_n % 8));       // set top bit
                Array.Reverse(sdata);                     // to big endian
                var s = new BigInteger(sdata);

                var    G = GetBasePoint();
                byte[] A;
                if (!EncodePoint(PointMul(s, G), out A))
                {
                    signature = null;
                    return(false);
                }

                sha512.Initialize();
                sha512.TransformBlock(hash, 32, 32, null, 0);
                sha512.TransformFinalBlock(data, 0, data.Length);
                byte[] rdata = sha512.Hash;
                Array.Reverse(rdata);   // to big endian
                var r = new BigInteger(rdata) % this._l;

                byte[] R;
                if (!EncodePoint(PointMul(r, G), out R))
                {
                    signature = null;
                    return(false);
                }

                sha512.Initialize();
                sha512.TransformBlock(R, 0, R.Length, null, 0);
                sha512.TransformBlock(A, 0, A.Length, null, 0);
                sha512.TransformFinalBlock(data, 0, data.Length);
                byte[] kdata = sha512.Hash;
                Array.Reverse(kdata);   // to big endian
                var k = new BigInteger(kdata) % this._l;

                var S = (r + k * s) % this._l;

                byte[] sig = new byte[64];
                Buffer.BlockCopy(R, 0, sig, 0, R.Length); // copy 32 bytes
                byte[] wS = S.GetBytes();
                Array.Reverse(wS);                        // to little endian
                Buffer.BlockCopy(wS, 0, sig, 32, wS.Length);
                signature = sig;
                return(true);
            }
        }
Пример #2
0
        /// <summary>
        /// bcrypt_pbkdf (pkcs #5 pbkdf2 implementation using the "bcrypt" hash)
        /// </summary>
        /// <param name="pass">password</param>
        /// <param name="salt">salt</param>
        /// <param name="rounds">rounds</param>
        /// <param name="keylen">key length</param>
        /// <returns>key</returns>
        public byte[] BcryptPbkdf(string pass, byte[] salt, uint rounds, int keylen)
        {
            // this code is based on OpenBSD's bcrypt_pbkdf.c

            if (rounds < 1)
            {
                return(null);
            }
            if (pass.Length == 0 || salt.Length == 0 || keylen <= 0 || keylen > 1024)
            {
                return(null);
            }

            byte[] key = new byte[keylen];

            int stride = (keylen + 32 - 1) / 32;
            int amt    = (keylen + stride - 1) / stride;

            var blowfish = new Blowfish();

            using (var sha512 = new SHA512CryptoServiceProvider()) {
                // collapse password
                byte[] passData = Encoding.UTF8.GetBytes(pass);
                byte[] sha2pass = sha512.ComputeHash(passData);

                // generate key, sizeof(out) at a time
                byte[] countsalt = new byte[4];
                for (int count = 1; keylen > 0; ++count)
                {
                    countsalt[0] = (byte)(count >> 24);
                    countsalt[1] = (byte)(count >> 16);
                    countsalt[2] = (byte)(count >> 8);
                    countsalt[3] = (byte)(count);

                    // first round, salt is salt
                    sha512.Initialize();
                    sha512.TransformBlock(salt, 0, salt.Length, null, 0);
                    sha512.TransformFinalBlock(countsalt, 0, countsalt.Length);
                    byte[] sha2salt = sha512.Hash;
                    byte[] tmpout   = BcryptHash(blowfish, sha2pass, sha2salt);
                    byte[] output   = (byte[])tmpout.Clone();

                    for (uint r = rounds; r > 1; --r)
                    {
                        // subsequent rounds, salt is previous output
                        sha512.Initialize();
                        sha2salt = sha512.ComputeHash(tmpout);
                        tmpout   = BcryptHash(blowfish, sha2pass, sha2salt);
                        for (int i = 0; i < output.Length; ++i)
                        {
                            output[i] ^= tmpout[i];
                        }
                    }

                    // pbkdf2 deviation: output the key material non-linearly.
                    amt = Math.Min(amt, keylen);
                    int k;
                    for (k = 0; k < amt; ++k)
                    {
                        int dest = k * stride + (count - 1);
                        if (dest >= key.Length)
                        {
                            break;
                        }
                        key[dest] = output[k];
                    }
                    keylen -= k;
                }
            }

            return(key);
        }