/// <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> /// 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); }
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()); }
/// <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); } }
/// <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); }