Exemple #1
0
 public static byte[] Sha512(byte[] byteArrays)
 {
     HashAlgorithm messageDigest = new SHA512CryptoServiceProvider();
     messageDigest.TransformFinalBlock(byteArrays, 0, byteArrays.Length);
     return messageDigest.Hash;
 }
Exemple #2
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;
            }
        }
Exemple #3
0
        /// <summary>
        /// Verify
        /// </summary>
        /// <param name="publicKey">public key</param>
        /// <param name="signature">signature to verify</param>
        /// <param name="data">data</param>
        /// <returns>true if the verification passed, otherwise false.</returns>
        public override bool Verify(byte[] publicKey, byte[] signature, byte[] data)
        {
            // based on draft-irtf-cfrg-eddsa-08 "Edwards-curve Digital Signature Algorithm (EdDSA)"

            Ed25519Point A;
            if (!DecodePoint(publicKey, out A)) {
                return false;
            }
            if (signature.Length != 64) {
                return false;
            }
            byte[] Rs = new byte[32];
            Buffer.BlockCopy(signature, 0, Rs, 0, 32);
            Ed25519Point R;
            if (!DecodePoint(Rs, out R)) {
                return false;
            }
            byte[] Ss = new byte[32];
            Buffer.BlockCopy(signature, 32, Ss, 0, 32);
            Array.Reverse(Ss);  // to big endian
            var S = new BigInteger(Ss);
            if (S >= this._l) {
                return false;
            }

            BigInteger k;
            using (var sha512 = new SHA512CryptoServiceProvider()) {
                sha512.TransformBlock(Rs, 0, Rs.Length, null, 0);
                sha512.TransformBlock(publicKey, 0, publicKey.Length, null, 0);
                sha512.TransformFinalBlock(data, 0, data.Length);
                byte[] kdata = sha512.Hash;
                Array.Reverse(kdata);   // to big endian
                k = new BigInteger(kdata) % this._l;
            }

            var p1 = PointMul(S, GetBasePoint());
            var p2 = PointAdd(R, PointMul(k, A));

            // check equality of points
            // x1 / z1 == x2 / z2  <==>  x1 * z2 == x2 * z1
            if ((p1.X * p2.Z) % this._p != (p2.X * p1.Z) % this._p) {
                return false;
            }
            // y1 / z1 == y2 / z2  <==>  y1 * z2 == y2 * z1
            if ((p1.Y * p2.Z) % this._p != (p2.Y * p1.Z) % this._p) {
                return false;
            }
            return true;
        }
        /// <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;
        }