Пример #1
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);
        }
Пример #2
0
            /// <summary>
            /// Calculates a quick checksum.
            /// NOTE: In our case we create SHA512 by using the first and last block (if available)
            /// </summary>
            /// <returns></returns>
            private byte[] _CalculateChecksum()
            {
                var length = this._FileSize;

                if (length <= 0)
                {
                    return(_EMPTY_BYTES);
                }

                byte[] result;

                using (var provider = new SHA512CryptoServiceProvider())
                    using (var stream = new FileStream(this._Source.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)) {
                        var buffer = new byte[_COMPARISON_BLOCK_SIZE];

                        // read first block
                        var bytesRead = stream.Read(buffer, 0, _COMPARISON_BLOCK_SIZE);
                        if (length > _COMPARISON_BLOCK_SIZE)
                        {
                            provider.TransformBlock(buffer, 0, bytesRead, buffer, 0);

                            // read last block (or what is left of it)
                            stream.Seek(Math.Max(_COMPARISON_BLOCK_SIZE, length - _COMPARISON_BLOCK_SIZE), SeekOrigin.Begin);
                            bytesRead = stream.Read(buffer, 0, _COMPARISON_BLOCK_SIZE);
                        }

                        provider.TransformFinalBlock(buffer, 0, bytesRead);
                        result = provider.Hash;
                    }

                return(result);
            }
Пример #3
0
        public async Task <string> Value()
        {
            using var stream = new FileStream(_filename, FileMode.Open, FileAccess.Read, FileShare.Read, FileBufferSize, true);
            using var sha512 = new SHA512CryptoServiceProvider();

            var buffer = new byte[FileBufferSize];
            int bytesRead;

            while ((bytesRead = await stream.ReadAsync(buffer, 0, FileBufferSize)) > 0)
            {
                sha512.TransformBlock(buffer, 0, bytesRead, null, 0);
            }
            sha512.TransformFinalBlock(buffer, 0, 0);

            return(BitConverter.ToString(sha512.Hash).Replace("-", "").ToLowerInvariant());
        }
Пример #4
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);
            }
        }
Пример #5
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);
        }