예제 #1
0
        public override bool Verify(ArraySegment <byte> signature, ArraySegment <byte> message, ArraySegment <byte> 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

            ByteIntegerConverter.Array8LoadLittleEndian32(out Array8 <uint> internalKey, key.Array, key.Offset);
            Poly1305Donna.poly1305_auth(tempBytes, 0, message.Array, message.Offset, message.Count, ref internalKey);
            return(CryptoBytes.ConstantTimeEquals(new ArraySegment <byte>(tempBytes), signature));
        }
예제 #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

            ByteIntegerConverter.Array8LoadLittleEndian32(out Array8 <uint> internalKey, key, 0);
            Poly1305Donna.poly1305_auth(tempBytes, 0, message, 0, message.Length, ref internalKey);
            return(CryptoBytes.ConstantTimeEquals(tempBytes, signature));
        }
예제 #3
0
        public override void Sign(ArraySegment <byte> signature, ArraySegment <byte> message, ArraySegment <byte> 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");
            }

            ByteIntegerConverter.Array8LoadLittleEndian32(out var internalKey, key.Array, key.Offset);
            Poly1305Donna.poly1305_auth(signature.Array, signature.Offset, message.Array, message.Offset, message.Count, ref internalKey);
        }
예제 #4
0
        private static void EncryptInternal(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;
            var             tempBytes = new byte[64];//todo: remove allocation
            Array8 <UInt32> 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 < count; i++)
                {
                    ciphertext[16 + ciphertextOffset + i] = (byte)(message[messageOffset + i] ^ tempBytes[i]);
                }
            }

            // later iterations
            int blockOffset = 32;

            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[16 + ciphertextOffset + blockOffset + i] = (byte)(message[messageOffset + blockOffset + i] ^ tempBytes[i]);
                }
                blockOffset += 64;
            }

            // compute MAC
            Poly1305Donna.poly1305_auth(ciphertext, ciphertextOffset, ciphertext, ciphertextOffset + 16, messageLength, ref poly1305Key);
        }
예제 #5
0
        public override byte[] Sign(byte[] message, byte[] key)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }
            if (key.Length != 32)
            {
                throw new ArgumentException("Invalid key size", "key");
            }

            var result = new byte[16];

            ByteIntegerConverter.Array8LoadLittleEndian32(out var internalKey, key, 0);
            Poly1305Donna.poly1305_auth(result, 0, message, 0, message.Length, ref internalKey);
            return(result);
        }
        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 <uint> internalKey;

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

            Array16 <uint> temp;

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

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

                //first half is for Poly1305
                Array8 <uint> 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.HSalsa(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);
        }
        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 \