예제 #1
0
        /// <summary>
        /// Finalizes SHA-512 hashing
        /// </summary>
        /// <param name="output">Output buffer</param>
        public void Finalize(ArraySegment <byte> output)
        {
            Contract.Requires <ArgumentNullException>(output.Array != null);
            Contract.Requires <ArgumentException>(output.Count == 64);

            Update(_padding, 0, _padding.Length);
            Array16 <ulong> block;

            ByteIntegerConverter.Array16LoadBigEndian64(out block, _buffer, 0);
            CryptoBytes.InternalWipe(_buffer, 0, _buffer.Length);
            int bytesInBuffer = (int)_totalBytes & (BlockSize - 1);

            if (bytesInBuffer > BlockSize - 16)
            {
                Sha512Internal.Core(out _state, ref _state, ref block);
                block = default(Array16 <ulong>);
            }
            block.x15 = (_totalBytes - 1) * 8;
            Sha512Internal.Core(out _state, ref _state, ref block);

            ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 0, _state.x0);
            ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 8, _state.x1);
            ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 16, _state.x2);
            ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 24, _state.x3);
            ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 32, _state.x4);
            ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 40, _state.x5);
            ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 48, _state.x6);
            ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 56, _state.x7);
            _state = default(Array8 <ulong>);
        }
예제 #2
0
        public override bool Verify(byte[] signature, byte[] message, byte[] key)
        {
            if (signature == null)
            {
                throw new ArgumentNullException("signature");
            }
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }
            if (signature.Length != 16)
            {
                throw new ArgumentException("Invalid signature size", "signature");
            }
            if (key.Length != 32)
            {
                throw new ArgumentException("Invalid key size", "key");
            }

            var tempBytes = new byte[16];//todo: remove allocation

            Array8 \ \ internalKey;
            ByteIntegerConverter.Array8LoadLittleEndian32(out internalKey, key, 0);
            Poly1305Donna.poly1305_auth(tempBytes, 0, message, 0, message.Length, ref internalKey);
            return(CryptoBytes.ConstantTimeEquals(tempBytes, signature));
        }
예제 #3
0
        public override bool Verify(ArraySegment \ \ signature, ArraySegment \ \ message, ArraySegment \ \ key)
        {
            if (signature.Array == null)
            {
                throw new ArgumentNullException("signature.Array");
            }
            if (message.Array == null)
            {
                throw new ArgumentNullException("message.Array");
            }
            if (key.Array == null)
            {
                throw new ArgumentNullException("key.Array");
            }
            if (key.Count != 32)
            {
                throw new ArgumentException("Invalid key size", "key");
            }
            if (signature.Count != 16)
            {
                throw new ArgumentException("Invalid signature size", "signature");
            }

            var tempBytes = new byte[16];//todo: remove allocation

            Array8 \ \ internalKey;
            ByteIntegerConverter.Array8LoadLittleEndian32(out internalKey, key.Array, key.Offset);
            Poly1305Donna.poly1305_auth(tempBytes, 0, message.Array, message.Offset, message.Count, ref internalKey);
            return(CryptoBytes.ConstantTimeEquals(new ArraySegment \ \ (tempBytes), signature));
        }
예제 #4
0
        public void Finish(ArraySegment\\ output)
        {
            if (output.Array == null)
                throw new ArgumentNullException("output.Array");
            if (output.Count != 64)
                throw new ArgumentException("output.Count must be 64");

            Update(_padding, 0, _padding.Length);
            Array16\\ block;
            ByteIntegerConverter.Array16LoadBigEndian64(out block, _buffer, 0);
            CryptoBytes.InternalWipe(_buffer, 0, _buffer.Length);
            int bytesInBuffer = (int)_totalBytes & (BlockSize - 1);
            if (bytesInBuffer \>\ BlockSize - 16)
            {
                Sha512Internal.Core(out _state, ref _state, ref block);
                block = default(Array16\\);
            }
            block.x15 = (_totalBytes - 1) * 8;
            Sha512Internal.Core(out _state, ref _state, ref block);

            ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 0, _state.x0);
            ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 8, _state.x1);
            ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 16, _state.x2);
            ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 24, _state.x3);
            ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 32, _state.x4);
            ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 40, _state.x5);
            ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 48, _state.x6);
            ByteIntegerConverter.StoreBigEndian64(output.Array, output.Offset + 56, _state.x7);
            _state = default(Array8\\);
        }
예제 #5
0
        private static void ProcessInternal(byte[] ciphertext, int ciphertextOffset, byte[] message, int messageOffset, int messageLength, byte[] key, int keyOffset, byte[] nonce, int nonceOffset)
        {
            Array16 <UInt32> internalKey;

            PrepareInternalKey(out internalKey, key, keyOffset, nonce, nonceOffset);

            Array16 <UInt32> temp;

            byte[] tempBytes = new byte[64];//todo: remove allocation

            int blockOffset = 0;

            while (blockOffset < messageLength)
            {
                //internalKey.x8++;
                SalsaCore.Salsa(out temp, ref internalKey, 20);
                ByteIntegerConverter.Array16StoreLittleEndian32(tempBytes, 0, ref temp);
                int count = Math.Min(64, messageLength - blockOffset);
                for (int i = 0; i < count; i++)
                {
                    ciphertext[ciphertextOffset + blockOffset + i] = (byte)(message[messageOffset + blockOffset + i] ^ tempBytes[i]);
                }
                blockOffset += 64;
                internalKey.x8++;
            }
            CryptoBytes.Wipe(tempBytes); // DON'T LEAK!
        }
예제 #6
0
        public static void KeyExchange(Span <byte> sharedKey, ReadOnlySpan <byte> publicKey, ReadOnlySpan <byte> privateKey)
        {
            if (sharedKey.Length != 32)
            {
                throw new ArgumentException("sharedKey.Count != 32");
            }
            if (publicKey.Length != 32)
            {
                throw new ArgumentException("publicKey.Count != 32");
            }
            if (privateKey.Length != 64)
            {
                throw new ArgumentException("privateKey.Count != 64");
            }

            FieldOperations.fe_frombytes(out var edwardsY, publicKey);
            FieldOperations.fe_1(out var edwardsZ);
            MontgomeryCurve25519.EdwardsToMontgomeryX(out var montgomeryX, ref edwardsY, ref edwardsZ);
            Span <byte> h = stackalloc byte[64];

            Sha512.Hash(privateKey.Slice(0, 32), h);
            ScalarOperations.sc_clamp(h);
            MontgomeryOperations.scalarmult(out var sharedMontgomeryX, h, in montgomeryX);
            CryptoBytes.Wipe(h);
            FieldOperations.fe_tobytes(sharedKey, in sharedMontgomeryX);
        }
예제 #7
0
 public static byte[] ExpandedPrivateKeyFromSeed(byte[] privateKeySeed)
 {
     byte[] privateKey;
     byte[] publicKey;
     KeyPairFromSeed(out publicKey, out privateKey, privateKeySeed);
     CryptoBytes.Wipe(publicKey);
     return(privateKey);
 }
예제 #8
0
        public void Update(byte[] data, int offset, int count)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException("offset");
            }
            if (count < 0)
            {
                throw new ArgumentOutOfRangeException("count");
            }
            if (data.Length - offset < count)
            {
                throw new ArgumentException("Requires offset + count <= data.Length");
            }

            Array16 <ulong> block;
            int             bytesInBuffer = (int)_totalBytes & (BlockSize - 1);

            _totalBytes += (uint)count;

            if (_totalBytes >= ulong.MaxValue / 8)
            {
                throw new InvalidOperationException("Too much data");
            }
            // Fill existing buffer
            if (bytesInBuffer != 0)
            {
                var toCopy = Math.Min(BlockSize - bytesInBuffer, count);
                Buffer.BlockCopy(data, offset, _buffer, bytesInBuffer, toCopy);
                offset        += toCopy;
                count         -= toCopy;
                bytesInBuffer += toCopy;
                if (bytesInBuffer == BlockSize)
                {
                    ByteIntegerConverter.Array16LoadBigEndian64(out block, _buffer, 0);
                    Sha512Internal.Core(out _state, ref _state, ref block);
                    CryptoBytes.InternalWipe(_buffer, 0, _buffer.Length);
                    bytesInBuffer = 0;
                }
            }
            // Hash complete blocks without copying
            while (count >= BlockSize)
            {
                ByteIntegerConverter.Array16LoadBigEndian64(out block, data, offset);
                Sha512Internal.Core(out _state, ref _state, ref block);
                offset += BlockSize;
                count  -= BlockSize;
            }
            // Copy remainder into buffer
            if (count > 0)
            {
                Buffer.BlockCopy(data, offset, _buffer, bytesInBuffer, count);
            }
        }
예제 #9
0
        public static byte[] ExpandedPrivateKeyFromSeed(ReadOnlySpan <byte> privateKeySeed)
        {
            Span <byte> publicKey  = stackalloc byte[PublicKeySizeInBytes];
            var         privateKey = new byte[ExpandedPrivateKeySizeInBytes];

            KeyPairFromSeed(publicKey, privateKey, privateKeySeed);
            CryptoBytes.Wipe(publicKey);
            return(privateKey);
        }
예제 #10
0
        /// <summary>
        /// Calculate public key from private key seed
        /// </summary>
        /// <param name="privateKeySeed">Private key seed value</param>
        /// <returns></returns>
        public static byte[] PublicKeyFromSeed(byte[] privateKeySeed)
        {
            Contract.Requires <ArgumentNullException>(privateKeySeed != null);
            Contract.Requires <ArgumentException>(privateKeySeed.Length == PrivateKeySeedSize);

            byte[] privateKey;
            byte[] publicKey;
            KeyPairFromSeed(out publicKey, out privateKey, privateKeySeed);
            CryptoBytes.Wipe(privateKey);
            return(publicKey);
        }
예제 #11
0
        public void Finish(Span <byte> output)
        {
            if (output.Length != 64)
            {
                throw new ArgumentException("output.Count must be 64");
            }

            Update(_padding);
            Array16 <ulong> block;

            ByteIntegerConverter.Array16LoadBigEndian64(out block, _buffer);
            CryptoBytes.Wipe(_buffer, 0, _buffer.Length);
            int bytesInBuffer = (int)_totalBytes & (BlockSize - 1);

            if (bytesInBuffer > BlockSize - 16)
            {
                Sha512Internal.Core(out _state, in _state, in block);
                block = default;
            }
            block = new Array16 <ulong>(
                block.x0,
                block.x1,
                block.x2,
                block.x3,
                block.x4,
                block.x5,
                block.x6,
                block.x7,
                block.x8,
                block.x9,
                block.x10,
                block.x11,
                block.x12,
                block.x13,
                block.x14,
                (_totalBytes - 1) * 8);

            Sha512Internal.Core(out _state, in _state, in block);

            BinaryPrimitives.WriteUInt64BigEndian(output.Slice(0), _state.x0);
            BinaryPrimitives.WriteUInt64BigEndian(output.Slice(8), _state.x1);
            BinaryPrimitives.WriteUInt64BigEndian(output.Slice(16), _state.x2);
            BinaryPrimitives.WriteUInt64BigEndian(output.Slice(24), _state.x3);
            BinaryPrimitives.WriteUInt64BigEndian(output.Slice(32), _state.x4);
            BinaryPrimitives.WriteUInt64BigEndian(output.Slice(40), _state.x5);
            BinaryPrimitives.WriteUInt64BigEndian(output.Slice(48), _state.x6);
            BinaryPrimitives.WriteUInt64BigEndian(output.Slice(56), _state.x7);
            _state = default;
        }
예제 #12
0
        public static void KeyExchange(ArraySegment <byte> sharedKey, ArraySegment <byte> publicKey, ArraySegment <byte> privateKey)
        {
            if (sharedKey.Array == null)
            {
                throw new ArgumentNullException("sharedKey.Array");
            }
            if (publicKey.Array == null)
            {
                throw new ArgumentNullException("publicKey.Array");
            }
            if (privateKey.Array == null)
            {
                throw new ArgumentNullException("privateKey");
            }
            if (sharedKey.Count != 32)
            {
                throw new ArgumentException("sharedKey.Count != 32");
            }
            if (publicKey.Count != 32)
            {
                throw new ArgumentException("publicKey.Count != 32");
            }
            if (privateKey.Count != 64)
            {
                throw new ArgumentException("privateKey.Count != 64");
            }

            FieldElement montgomeryX, edwardsY, edwardsZ, sharedMontgomeryX;

            FieldOperations.fe_frombytes(out edwardsY, publicKey.Array, publicKey.Offset);
            FieldOperations.fe_1(out edwardsZ);
            MontgomeryCurve25519.EdwardsToMontgomeryX(out montgomeryX, ref edwardsY, ref edwardsZ);
            var blake2bConfig = new Blake2BConfig
            {
                OutputSizeInBytes = 64
            };
            var hasher = Blake2B.Create(blake2bConfig);

            hasher.Update(privateKey.Array, privateKey.Offset, 32);
            byte[] h = hasher.Finish();
            //byte[] h = Sha512.Hash(privateKey.Array, privateKey.Offset, 32);//ToDo: Remove alloc
            ScalarOperations.sc_clamp(h, 0);
            MontgomeryOperations.scalarmult(out sharedMontgomeryX, h, 0, ref montgomeryX);
            CryptoBytes.Wipe(h);
            FieldOperations.fe_tobytes(sharedKey.Array, sharedKey.Offset, ref sharedMontgomeryX);
            MontgomeryCurve25519.KeyExchangeOutputHashNaCl(sharedKey.Array, sharedKey.Offset);
        }
예제 #13
0
        public static void crypto_sign2(
            byte[] sig,
            byte[] m,
            byte[] sk,
            int keylen)
        {
            byte[]         privHash   = new byte[64];
            byte[]         seededHash = new byte[64];
            byte[]         result     = new byte[64];
            GroupElementP3 R          = new GroupElementP3();
            var            hasher     = new KeccakDigest(512);
            {
                var reversedPrivateKey = new byte[keylen];
                Array.Copy(sk, 0, reversedPrivateKey, 0, keylen);
                Array.Reverse(reversedPrivateKey);

                hasher.BlockUpdate(reversedPrivateKey, 0, keylen);
                hasher.DoFinal(privHash, 0);

                ScalarOperations.sc_clamp(privHash, 0);

                hasher.Reset();
                hasher.BlockUpdate(privHash, 32, 32);
                hasher.BlockUpdate(m, 0, m.Length);
                hasher.DoFinal(seededHash, 0);

                ScalarOperations.sc_reduce(seededHash);

                GroupOperations.ge_scalarmult_base(out R, seededHash, 0);
                GroupOperations.ge_p3_tobytes(sig, 0, ref R);

                hasher.Reset();
                hasher.BlockUpdate(sig, 0, 32);
                hasher.BlockUpdate(sk, keylen, 32);
                hasher.BlockUpdate(m, 0, m.Length);
                hasher.DoFinal(result, 0);

                ScalarOperations.sc_reduce(result);

                var s = new byte[32];//todo: remove allocation
                Array.Copy(sig, 32, s, 0, 32);
                ScalarOperations.sc_muladd(s, result, privHash, seededHash);
                Array.Copy(s, 0, sig, 32, 32);
                CryptoBytes.Wipe(s);
            }
        }
예제 #14
0
        /// <summary>
        /// Updates internal state with data from the provided array.
        /// </summary>
        /// <param name="data">Array of bytes</param>
        /// <param name="index">Offset of byte sequence</param>
        /// <param name="length">Sequence length</param>
        public void Update(byte[] data, int index, int length)
        {
            Contract.Requires <ArgumentNullException>(data != null);
            Contract.Requires <ArgumentOutOfRangeException>(index >= 0 && length >= 0);
            Contract.Requires <ArgumentException>((index + length) <= data.Length);

            Array16 <ulong> block;
            int             bytesInBuffer = (int)_totalBytes & (BlockSize - 1);

            _totalBytes += (uint)length;

            if (_totalBytes >= ulong.MaxValue / 8)
            {
                throw new InvalidOperationException("Too much data");
            }
            // Fill existing buffer
            if (bytesInBuffer != 0)
            {
                var toCopy = Math.Min(BlockSize - bytesInBuffer, length);
                Buffer.BlockCopy(data, index, _buffer, bytesInBuffer, toCopy);
                index         += toCopy;
                length        -= toCopy;
                bytesInBuffer += toCopy;
                if (bytesInBuffer == BlockSize)
                {
                    ByteIntegerConverter.Array16LoadBigEndian64(out block, _buffer, 0);
                    Sha512Internal.Core(out _state, ref _state, ref block);
                    CryptoBytes.InternalWipe(_buffer, 0, _buffer.Length);
                    bytesInBuffer = 0;
                }
            }
            // Hash complete blocks without copying
            while (length >= BlockSize)
            {
                ByteIntegerConverter.Array16LoadBigEndian64(out block, data, index);
                Sha512Internal.Core(out _state, ref _state, ref block);
                index  += BlockSize;
                length -= BlockSize;
            }
            // Copy remainder into buffer
            if (length > 0)
            {
                Buffer.BlockCopy(data, index, _buffer, bytesInBuffer, length);
            }
        }
예제 #15
0
        public static void KeyExchange(ArraySegment <byte> sharedKey, ArraySegment <byte> publicKey, ArraySegment <byte> privateKey)
        {
            if (sharedKey.Array == null)
            {
                throw new ArgumentNullException("sharedKey.Array");
            }
            if (publicKey.Array == null)
            {
                throw new ArgumentNullException("publicKey.Array");
            }
            if (privateKey.Array == null)
            {
                throw new ArgumentNullException("privateKey");
            }
            if (sharedKey.Count != 32)
            {
                throw new ArgumentException("sharedKey.Count != 32");
            }
            if (publicKey.Count != 32)
            {
                throw new ArgumentException("publicKey.Count != 32");
            }
            if (privateKey.Count != 64)
            {
                throw new ArgumentException("privateKey.Count != 64");
            }

            FieldElement montgomeryX, edwardsY, edwardsZ, sharedMontgomeryX;

            FieldOperations.fe_frombytes(out edwardsY, publicKey.Array, publicKey.Offset);
            FieldOperations.fe_1(out edwardsZ);
            MontgomeryCurve25519.EdwardsToMontgomeryX(out montgomeryX, ref edwardsY, ref edwardsZ);
            var hasher = Blake2Fast.Blake2b.CreateIncrementalHasher(64);

            hasher.Update(new ArraySegment <byte>(privateKey.Array, privateKey.Offset, 32));
            byte[] h = hasher.Finish();
            ScalarOperations.sc_clamp(h, 0);
            MontgomeryOperations.scalarmult(out sharedMontgomeryX, h, 0, ref montgomeryX);
            CryptoBytes.Wipe(h);
            FieldOperations.fe_tobytes(sharedKey.Array, sharedKey.Offset, ref sharedMontgomeryX);
            MontgomeryCurve25519.KeyExchangeOutputHashNaCl(sharedKey.Array, sharedKey.Offset);
        }
예제 #16
0
        public void Update(ReadOnlySpan <byte> data)
        {
            Array16 <ulong> block;
            int             bytesInBuffer = (int)_totalBytes & (BlockSize - 1);

            _totalBytes += (uint)data.Length;
            var bufferSpan = _buffer.AsSpan();

            if (_totalBytes >= ulong.MaxValue / 8)
            {
                throw new InvalidOperationException("Too much data");
            }
            // Fill existing buffer
            if (bytesInBuffer != 0)
            {
                var toCopy = Math.Min(BlockSize - bytesInBuffer, data.Length);
                data.Slice(0, toCopy).CopyTo(bufferSpan.Slice(bytesInBuffer));
                data = data.Slice(toCopy);

                bytesInBuffer += toCopy;
                if (bytesInBuffer == BlockSize)
                {
                    ByteIntegerConverter.Array16LoadBigEndian64(out block, _buffer);
                    Sha512Internal.Core(out _state, in _state, in block);
                    CryptoBytes.Wipe(_buffer, 0, _buffer.Length);
                    bytesInBuffer = 0;
                }
            }
            // Hash complete blocks without copying
            while (data.Length >= BlockSize)
            {
                ByteIntegerConverter.Array16LoadBigEndian64(out block, data);
                Sha512Internal.Core(out _state, in _state, in block);
                data = data.Slice(BlockSize);
            }
            // Copy remainder into buffer
            if (data.Length > 0)
            {
                data.CopyTo(bufferSpan.Slice(bytesInBuffer));
            }
        }
예제 #17
0
        public static void KeyExchange(ArraySegment \ \ sharedKey, ArraySegment \ \ publicKey, ArraySegment \ \ privateKey)
        {
            if (sharedKey.Array == null)
            {
                throw new ArgumentNullException("sharedKey.Array");
            }
            if (publicKey.Array == null)
            {
                throw new ArgumentNullException("publicKey.Array");
            }
            if (privateKey.Array == null)
            {
                throw new ArgumentNullException("privateKey");
            }
            if (sharedKey.Count != 32)
            {
                throw new ArgumentException("sharedKey.Count != 32");
            }
            if (publicKey.Count != 32)
            {
                throw new ArgumentException("publicKey.Count != 32");
            }
            if (privateKey.Count != 64)
            {
                throw new ArgumentException("privateKey.Count != 64");
            }

            FieldElement montgomeryX, edwardsY, edwardsZ, sharedMontgomeryX;

            FieldOperations.fe_frombytes(out edwardsY, publicKey.Array, publicKey.Offset);
            FieldOperations.fe_1(out edwardsZ);
            MontgomeryCurve25519.EdwardsToMontgomeryX(out montgomeryX, ref edwardsY, ref edwardsZ);
            byte[] h = Sha512.Hash(privateKey.Array, privateKey.Offset, 32);//ToDo: Remove alloc
            ScalarOperations.sc_clamp(h, 0);
            MontgomeryOperations.scalarmult(out sharedMontgomeryX, h, 0, ref montgomeryX);
            CryptoBytes.Wipe(h);
            FieldOperations.fe_tobytes(sharedKey.Array, sharedKey.Offset, ref sharedMontgomeryX);
            MontgomeryCurve25519.KeyExchangeOutputHashNaCl(sharedKey.Array, sharedKey.Offset);
        }
        private static bool DecryptInternal(byte[] plaintext, int plaintextOffset, byte[] ciphertext, int ciphertextOffset, int ciphertextLength, byte[] key, int keyOffset, byte[] nonce, int nonceOffset)
        {
            int plaintextLength = ciphertextLength - MacSizeInBytes;
            Array16\\ internalKey;
            PrepareInternalKey(out internalKey, key, keyOffset, nonce, nonceOffset);

            Array16\\ temp;
            var tempBytes = new byte[64];//todo: remove allocation

            // first iteration
            {
                SalsaCore.Salsa(out temp, ref internalKey, 20);

                //first half is for Poly1305
                Array8\\ poly1305Key;
                poly1305Key.x0 = temp.x0;
                poly1305Key.x1 = temp.x1;
                poly1305Key.x2 = temp.x2;
                poly1305Key.x3 = temp.x3;
                poly1305Key.x4 = temp.x4;
                poly1305Key.x5 = temp.x5;
                poly1305Key.x6 = temp.x6;
                poly1305Key.x7 = temp.x7;

                // compute MAC
                Poly1305Donna.poly1305_auth(tempBytes, 0, ciphertext, ciphertextOffset + 16, plaintextLength, ref poly1305Key);
                if (!CryptoBytes.ConstantTimeEquals(tempBytes, 0, ciphertext, ciphertextOffset, MacSizeInBytes))
                {
                    Array.Clear(plaintext, plaintextOffset, plaintextLength);
                    return false;
                }

                // rest for the message
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 0, temp.x8);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 4, temp.x9);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 8, temp.x10);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 12, temp.x11);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 16, temp.x12);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 20, temp.x13);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 24, temp.x14);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 28, temp.x15);
                int count = Math.Min(32, plaintextLength);
                for (int i = 0; i \\ internalKey;
            PrepareInternalKey(out internalKey, key, keyOffset, nonce, nonceOffset);

            Array16\\ temp;
            var tempBytes = new byte[64];//todo: remove allocation
            Array8\\ poly1305Key;

            // first iteration
            {
                SalsaCore.Salsa(out temp, ref internalKey, 20);

                //first half is for Poly1305
                poly1305Key.x0 = temp.x0;
                poly1305Key.x1 = temp.x1;
                poly1305Key.x2 = temp.x2;
                poly1305Key.x3 = temp.x3;
                poly1305Key.x4 = temp.x4;
                poly1305Key.x5 = temp.x5;
                poly1305Key.x6 = temp.x6;
                poly1305Key.x7 = temp.x7;

                // second half for the message
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 0, temp.x8);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 4, temp.x9);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 8, temp.x10);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 12, temp.x11);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 16, temp.x12);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 20, temp.x13);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 24, temp.x14);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 28, temp.x15);
                int count = Math.Min(32, messageLength);
                for (int i = 0; i \
예제 #19
0
        private static bool DecryptInternal(byte[] plaintext, int plaintextOffset, byte[] ciphertext, int ciphertextOffset, int ciphertextLength, byte[] key, int keyOffset, byte[] nonce, int nonceOffset)
        {
            int plaintextLength = ciphertextLength - MacSizeInBytes;
            Array16 <UInt32> internalKey;

            PrepareInternalKey(out internalKey, key, keyOffset, nonce, nonceOffset);

            Array16 <UInt32> temp;
            var tempBytes = new byte[64];//todo: remove allocation

            // first iteration
            {
                SalsaCore.Salsa(out temp, ref internalKey, 20);

                //first half is for Poly1305
                Array8 <UInt32> poly1305Key;
                poly1305Key.x0 = temp.x0;
                poly1305Key.x1 = temp.x1;
                poly1305Key.x2 = temp.x2;
                poly1305Key.x3 = temp.x3;
                poly1305Key.x4 = temp.x4;
                poly1305Key.x5 = temp.x5;
                poly1305Key.x6 = temp.x6;
                poly1305Key.x7 = temp.x7;

                // compute MAC
                Poly1305Donna.poly1305_auth(tempBytes, 0, ciphertext, ciphertextOffset + 16, plaintextLength, ref poly1305Key);
                if (!CryptoBytes.ConstantTimeEquals(tempBytes, 0, ciphertext, ciphertextOffset, MacSizeInBytes))
                {
                    Array.Clear(plaintext, plaintextOffset, plaintextLength);
                    return(false);
                }

                // rest for the message
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 0, temp.x8);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 4, temp.x9);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 8, temp.x10);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 12, temp.x11);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 16, temp.x12);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 20, temp.x13);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 24, temp.x14);
                ByteIntegerConverter.StoreLittleEndian32(tempBytes, 28, temp.x15);
                int count = Math.Min(32, plaintextLength);
                for (int i = 0; i < count; i++)
                {
                    plaintext[plaintextOffset + i] = (byte)(ciphertext[MacSizeInBytes + ciphertextOffset + i] ^ tempBytes[i]);
                }
            }

            // later iterations
            int blockOffset = 32;

            while (blockOffset < plaintextLength)
            {
                internalKey.x8++;
                SalsaCore.Salsa(out temp, ref internalKey, 20);
                ByteIntegerConverter.Array16StoreLittleEndian32(tempBytes, 0, ref temp);
                int count = Math.Min(64, plaintextLength - blockOffset);
                for (int i = 0; i < count; i++)
                {
                    plaintext[plaintextOffset + blockOffset + i] = (byte)(ciphertext[16 + ciphertextOffset + blockOffset + i] ^ tempBytes[i]);
                }
                blockOffset += 64;
            }
            return(true);
        }
예제 #20
0
 public static byte[] PublicKeyFromSeed(byte[] privateKeySeed)
 {
     KeyPairFromSeed(out var publicKey, out var privateKey, privateKeySeed);
     CryptoBytes.Wipe(privateKey);
     return(publicKey);
 }