예제 #1
0
파일: Message.cs 프로젝트: archerland/UCS-3
 public void Encrypt(byte[] plainText)
 {
     try
     {
         if (GetMessageType() == 20103)
         {
             var nonce =
                 GenericHash.Hash(
                     Client.CSNonce.Concat(Client.CPublicKey).Concat(Key.Crypto.PublicKey).ToArray(), null, 24);
             plainText = Client.CRNonce.Concat(Client.CSharedKey).Concat(plainText).ToArray();
             SetData(PublicKeyBox.Create(plainText, nonce, Key.Crypto.PrivateKey, Client.CPublicKey));
         }
         else if (GetMessageType() == 20104)
         {
             var nonce =
                 GenericHash.Hash(
                     Client.CSNonce.Concat(Client.CPublicKey).Concat(Key.Crypto.PublicKey).ToArray(), null, 24);
             plainText = Client.CRNonce.Concat(Client.CSharedKey).Concat(plainText).ToArray();
             SetData(PublicKeyBox.Create(plainText, nonce, Key.Crypto.PrivateKey, Client.CPublicKey));
             Client.CState = 2;
         }
         else
         {
             Client.CRNonce = Utilities.Increment(Utilities.Increment(Client.CRNonce));
             SetData(SecretBox.Create(plainText, Client.CRNonce, Client.CSharedKey).Skip(16).ToArray());
         }
     }
     catch (Exception ex)
     {
         Client.CState = 0;
     }
 }
예제 #2
0
        public void SavePrivateKey(SecureString password, string path = null)
        {
            Console.WriteLine("Set path if needed");
            if (string.IsNullOrEmpty(path))
            {
                path = (Environment.OSVersion.Platform == PlatformID.Unix) ?
                       Environment.GetEnvironmentVariable("HOME") :
                       Environment.ExpandEnvironmentVariables("%HOMEDRIVE%%HOMEPATH%");
                path += "/.cryptchat/" + Base32.ToBase32String(GenericHash.Hash(Encoding.ASCII.GetBytes(Username), null, 16));
            }
            Console.WriteLine("Create directory");
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            path += "/.pem";
            Console.WriteLine("Lock PrivateKey with password");
            var temp = SecretBox.Create(Convert.FromBase64String(PrivateKey),
                                        GenericHash.Hash(Encoding.ASCII.GetBytes(Id), null, 24),
                                        GenericHash.Hash(Encoding.ASCII.GetBytes(password), null, 32));
            var temp_key = Convert.ToBase64String(temp);

            Console.WriteLine("Save password-locked PrivateKey");
            if (!string.IsNullOrEmpty(temp_key))
            {
                File.WriteAllBytes(path, Convert.FromBase64String(temp_key));
            }
        }
예제 #3
0
파일: KeyExchange.cs 프로젝트: xiao5gee/C3
        public static byte[] Decrypt(byte[] message, byte[] rxKey)
        {
            var nonce  = message.Take(crypto_secretbox_NONCEBYTES).ToArray();
            var cipher = message.Skip(crypto_secretbox_NONCEBYTES).ToArray();

            return(SecretBox.Open(cipher, nonce, rxKey));
        }
예제 #4
0
 static string SecretboxEncryptionToBase64(string keyBase64, string plaintext)
 {
     byte[] nonce      = GenerateRandomNonce();
     byte[] data       = System.Text.Encoding.UTF8.GetBytes(plaintext);
     byte[] ciphertext = SecretBox.Create(plaintext, nonce, Base64Decoding(keyBase64));
     return(Base64Encoding(nonce) + ":" + Base64Encoding(ciphertext));
 }
예제 #5
0
        public void TestDisposal()
        {
            // this test is still bad.

            // "default" disposal
            byte[]             symkey = SecretBox.GenerateKey();
            SymmetricEncrypter abc    = new SymmetricEncrypter(symkey);

            abc.Dispose();

            SymmetricEncrypter def;

            try
            {
                def = new SymmetricEncrypter("Not a valid base64 code triggering an exception!");
            }
            catch (FormatException)
            {
                // disposal is called although constructor failed.
            }
            bool exceptionThrown = false;

            try
            {
                def = null;
            }
            catch (Exception)
            {
                exceptionThrown = true;
            }
            _ = new SymmetricEncrypter(symkey);
            Assert.IsFalse(exceptionThrown);
        }
예제 #6
0
        /// <summary>
        ///   Validates server acceptance message
        /// </summary>
        /// <remark>
        ///   Here the client verifies that the received message length is 80
        ///   bytes, then opens the encrypted box and verifies that the sent
        ///   message is server's signature to the derived shared secrets. With
        ///   this the handshake concludes.
        /// </remark>
        /// <exception cref="ArgumentException">
        ///   Thrown if the server's Accept <paramref name="msg"/> is not the
        ///   correct size or the signature is not valid.
        /// </exception>
        /// <param name="msg">
        ///   The received message, encrypted server's signature.
        /// </param>
        public void VerifyAccept(byte[] msg)
        {
            if (msg.Length != 80)
            {
                throw new ArgumentException("Incorrect message size");
            }

            var nonce = new byte[NONCE_SIZE];

            nonce.Initialize();

            // Concatenate the network key and derived secrets to obtain
            // the message key
            var key = CryptoHash.Sha256(
                Utils.Concat(_network_key, _shared_ab, _shared_aB, _shared_Ab)
                );

            var opened_msg = SecretBox.Open(msg, nonce, key);

            // Compute the message that it is supposed to be signed with the
            // server's long term key
            var hashed        = CryptoHash.Sha256(_shared_ab);
            var msg_to_verify = Utils.Concat(
                _network_key, detached_signature_A,
                _longterm_client_keypair.PublicKey, hashed
                );

            if (!PublicKeyAuth.VerifyDetached(opened_msg, msg_to_verify, _longterm_server_pk))
            {
                throw new ArgumentException("Invalid signature");
            }
        }
예제 #7
0
        /// <summary>
        ///   Computes the message that accepts the handshake.
        /// </summary>
        /// <remark>
        ///   Here the server computes a signature of the network key, the
        ///   signature of the long term client's public key and a sha 256 of
        ///   the shared ab secret. This is signed with the server's long term
        ///   private key.
        ///
        ///   This signature is encrypted using a sha 256 of the network key
        ///   and all of the derived secrets.
        /// </remark>
        /// <returns>
        ///   A byte array of length 80 consisting of the message.
        /// </returns>
        public byte[] Accept()
        {
            var detached_signature = PublicKeyAuth.SignDetached(
                Utils.Concat(
                    _network_key,
                    detached_signature_A,
                    _longterm_client_pk,
                    CryptoHash.Sha256(_shared_ab)
                    ),
                _longterm_server_keypair.PrivateKey
                );

            // A nonce consisting of 24 zeros
            var nonce = new byte[NONCE_SIZE];

            nonce.Initialize();

            var key = CryptoHash.Sha256(
                Utils.Concat(_network_key, _shared_ab, _shared_aB, _shared_Ab)
                );

            var msg = SecretBox.Create(detached_signature, nonce, key);

            return(msg);
        }
 public void OpenSecretBoxBadNonce()
 {
     SecretBox.Open(
         Utilities.HexToBinary("00000000000000000000000000000000b58d3c3e5ae78770b7db54e29e3885138a2f1ddb738f2309d9b38164"),
         Encoding.UTF8.GetBytes("ABCDEFGHIJKLMNOPQRSTUVW"),
         Encoding.UTF8.GetBytes("12345678901234567890123456789012"));
 }
예제 #9
0
        /// <summary>
        ///   Crafts the client Authenticate message
        /// </summary>
        /// <remark>
        ///   Consists of a signature of the network identifier, the server's
        ///   long term public key and a sha 256 of the derived secret ab,
        ///   concatenated with the client's long term public key. All
        ///   encrypted using the network identifier and the derived secrets
        ///   ab and aB.
        ///
        ///   This sets the object's <see cref="detached_signature_A"/>
        /// </remark>
        /// <returns>
        ///   The client Authenticate message
        /// </returns>
        public byte[] Authenticate()
        {
            var hash_ab = CryptoHash.Sha256(this._shared_ab);

            // Concatenate the network identifier, the server's public key and
            // the hash of the derived secret.
            var to_sign = Utils.Concat(
                _network_key, _longterm_server_pk, hash_ab
                );

            // Sign the first portion of the message and save it in the object
            // state for later use in the server accept verification.
            detached_signature_A = PublicKeyAuth.SignDetached(
                to_sign, _longterm_client_keypair.PrivateKey
                );

            // Create the plaintext message
            var plaintext = Utils.Concat(
                detached_signature_A, _longterm_client_keypair.PublicKey
                );

            // Create the key from the network key and the shared secrets
            var box_key = Utils.Concat(
                _network_key, _shared_ab, _shared_aB
                );

            // A nonce consisting of 24 zeros
            var nonce = new byte[NONCE_SIZE];

            nonce.Initialize();

            var msg = SecretBox.Create(plaintext, nonce, CryptoHash.Sha256(box_key));

            return(msg);
        }
 public void CreateDetachedSecretBoxBadNonce()
 {
     SecretBox.CreateDetached(
         Encoding.UTF8.GetBytes("Adam Caudill"),
         Encoding.UTF8.GetBytes("ABCDEFGHIJKLMNOPQRSTUVW"),
         Encoding.UTF8.GetBytes("12345678901234567890123456789012"));
 }
 public void CreateSecretBoxBadKey()
 {
     SecretBox.Create(
         Encoding.UTF8.GetBytes("Adam Caudill"),
         Encoding.UTF8.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWX"),
         Encoding.UTF8.GetBytes("123456789012345678901234567890"));
 }
예제 #12
0
        public static void DecryptPacket(ServerState state, byte[] packet)
        {
            using (var reader = new Reader(packet))
            {
                var ID = reader.ReadUInt16();
                reader.Seek(3, SeekOrigin.Current);
                var Version = reader.ReadUInt16();

                byte[] cipherText = reader.ReadAllBytes, plainText;

                var Name = Packet_Names.GetName(ID);

                switch (ID)
                {
                case 10100:
                {
                    plainText = cipherText;

                    break;
                }

                case 10101:
                {
                    state.ClientKey = cipherText.Take(32).ToArray();

                    var nonce = GenericHash.Hash(state.ClientKey.Concat(state.ServerKey.PublicKey).ToArray(), null,
                                                 24);

                    cipherText = cipherText.Skip(32).ToArray();

                    plainText = PublicKeyBox.Open(cipherText, nonce, state.ServerKey.PrivateKey, state.ClientKey);

                    state.SessionKey        = plainText.Take(24).ToArray();
                    state.ClientState.Nonce = plainText.Skip(24).Take(24).ToArray();

                    plainText = plainText.Skip(24).Skip(24).ToArray();

                    break;
                }

                default:
                {
                    state.ClientState.Nonce = Utilities.Increment(Utilities.Increment(state.ClientState.Nonce));

                    plainText = SecretBox.Open(new byte[16].Concat(cipherText).ToArray(), state.ClientState.Nonce,
                                               state.SharedKey);

                    break;
                }
                }

                ClientCrypto.EncryptPacket(state.ClientState, ID, Version, plainText);

                Console.WriteLine(
                    $"[{DateTime.Now.ToLongTimeString()}, CLIENT, {ID}] {Resources.Definition.Decode(new Reader(plainText), ID)}");

                Logger.Write(BitConverter.ToString(plainText).Replace("-", string.Empty), $"{ID}_{Name}",
                             LogType.PACKET);
            }
        }
예제 #13
0
 public void Decrypt()
 {
     try
     {
         if (m_vType == 10101)
         {
             var cipherText = m_vData;
             Client.CPublicKey = cipherText.Take(32).ToArray();
             Client.CSharedKey = Client.CPublicKey;
             Client.CRNonce    = Client.GenerateSessionKey();
             var nonce = GenericHash.Hash(Client.CPublicKey.Concat(Key.Crypto.PublicKey).ToArray(), null, 24);
             cipherText = cipherText.Skip(32).ToArray();
             var PlainText = PublicKeyBox.Open(cipherText, nonce, Key.Crypto.PrivateKey, Client.CPublicKey);
             Client.CSessionKey = PlainText.Take(24).ToArray();
             Client.CSNonce     = PlainText.Skip(24).Take(24).ToArray();
             SetData(PlainText.Skip(24).Skip(24).ToArray());
         }
         else if (m_vType != 10100)
         {
             Client.CSNonce = Utilities.Increment(Utilities.Increment(Client.CSNonce));
             SetData(SecretBox.Open(new byte[16].Concat(m_vData).ToArray(), Client.CSNonce, Client.CSharedKey));
         }
     }
     catch (Exception ex)
     {
         Client.CState = 0;
     }
 }
예제 #14
0
 /// <summary>
 /// Encrypts the file name.
 /// </summary>
 /// <param name="fileName">The file name.</param>
 /// <param name="fileNameLength">The length it will be filled up.</param>
 public void ProtectFileName(string fileName, int fileNameLength)
 {
     //fill up the filename to 256 bytes
     byte[] paddedFileName = Helper.Utils.StringToPaddedByteArray(fileName, fileNameLength);
     //encrypt the file name in the header
     this.Filename = SecretBox.Create(paddedFileName, this.FilenameNonce, this.UnencryptedEphemeralKey);
 }
예제 #15
0
 public void Decrypt()
 {
     try
     {
         if (this.m_vType == 10101)
         {
             byte[] array = this.m_vData;
             this.Client.CPublicKey = array.Take(32).ToArray <byte>();
             this.Client.CSharedKey = this.Client.CPublicKey;
             this.Client.CRNonce    = Client.GenerateSessionKey();
             byte[] nonce = GenericHash.Hash(this.Client.CPublicKey.Concat(Key.Crypto.PublicKey).ToArray <byte>(), null, 24);
             array = array.Skip(32).ToArray <byte>();
             byte[] source = PublicKeyBox.Open(array, nonce, Key.Crypto.PrivateKey, this.Client.CPublicKey);
             this.Client.CSessionKey = source.Take(24).ToArray <byte>();
             this.Client.CSNonce     = source.Skip(24).Take(24).ToArray <byte>();
             this.SetData(source.Skip(24).Skip(24).ToArray <byte>());
         }
         else
         {
             this.Client.CSNonce = Sodium.Utilities.Increment(Sodium.Utilities.Increment(this.Client.CSNonce));
             this.SetData(SecretBox.Open(new byte[16].Concat(this.m_vData).ToArray <byte>(), this.Client.CSNonce, this.Client.CSharedKey));
         }
     }
     catch (Exception)
     {
         this.Client.CState = 0;
     }
 }
예제 #16
0
        /// <summary>
        /// Takes a 'plaintext' Buffer of the message you want to encrypt,<para />
        /// and an array of recipient public keys.<para />
        /// Returns a message that is encrypted to all recipients<para />
        /// and openable by them with 'PrivateBox.MultiboxOpen'.<para />
        /// The 'recipients' must be between 1 and 7 items long.
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="recipients"></param>
        /// <param name="maxRecipients"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static byte[] Multibox(byte[] msg, byte[][] recipients, int maxRecipients = DEFAULT_MAX)
        {
            if (maxRecipients < 1 || maxRecipients > 255)
            {
                throw new ArgumentOutOfRangeException("max recipients must be between 1 and 255.");
            }

            if (recipients.Length > maxRecipients)
            {
                throw new ArgumentOutOfRangeException("max recipients is:" + maxRecipients + " found:" + recipients.Length);
            }

            var nonce   = RandomBytes(24);
            var key     = RandomBytes(32);
            var onetime = PublicKeyBox.GenerateKeyPair();

            var length_and_key = new List <byte>();

            length_and_key.Add((byte)recipients.Length);
            length_and_key.AddRange(key);

            var res = new List <byte>();

            res.AddRange(nonce);
            res.AddRange(onetime.PublicKey);

            foreach (var rec in recipients)
            {
                res.AddRange(SecretBox.Create(length_and_key.ToArray(), nonce, ScalarMult.Mult(onetime.PrivateKey, rec)));
            }
            res.AddRange(SecretBox.Create(msg, nonce, key));

            return(res.ToArray());
        }
예제 #17
0
 public void Encrypt(byte[] plainText)
 {
     try
     {
         if (this.GetMessageType() == 20103)
         {
             byte[] nonce = GenericHash.Hash(this.Client.CSNonce.Concat(this.Client.CPublicKey).Concat(Key.Crypto.PublicKey).ToArray <byte>(), null, 24);
             plainText = this.Client.CRNonce.Concat(this.Client.CSharedKey).Concat(plainText).ToArray <byte>();
             this.SetData(PublicKeyBox.Create(plainText, nonce, Key.Crypto.PrivateKey, this.Client.CPublicKey));
         }
         else if (this.GetMessageType() == 20104)
         {
             byte[] nonce2 = GenericHash.Hash(this.Client.CSNonce.Concat(this.Client.CPublicKey).Concat(Key.Crypto.PublicKey).ToArray <byte>(), null, 24);
             plainText = this.Client.CRNonce.Concat(this.Client.CSharedKey).Concat(plainText).ToArray <byte>();
             this.SetData(PublicKeyBox.Create(plainText, nonce2, Key.Crypto.PrivateKey, this.Client.CPublicKey));
             this.Client.CState = 2;
         }
         else
         {
             this.Client.CRNonce = Sodium.Utilities.Increment(Sodium.Utilities.Increment(this.Client.CRNonce));
             this.SetData(SecretBox.Create(plainText, this.Client.CRNonce, this.Client.CSharedKey).Skip(16).ToArray <byte>());
         }
     }
     catch (Exception)
     {
         this.Client.CState = 0;
     }
 }
예제 #18
0
        public static void EncryptPacket(Socket _Socket, ServerState _State, int _PacketID, int unknown, byte[] plainText)
        {
            byte[] cipherText;

            if (_PacketID == 20100)
            {
                cipherText = plainText;
            }
            else if (_PacketID == 20103)
            {
                byte[] nonce = GenericHash.Hash(_State.clientState.nonce.Concat(_State.clientKey).Concat(_State.serverKey.PublicKey).ToArray(), null, 24);
                plainText  = _State.nonce.Concat(_State.sharedKey).Concat(plainText).ToArray();
                cipherText = PublicKeyBox.Create(plainText, nonce, _State.serverKey.PrivateKey, _State.clientKey);
            }
            else if (_PacketID == 20104)
            {
                byte[] nonce = GenericHash.Hash(_State.clientState.nonce.Concat(_State.clientKey).Concat(_State.serverKey.PublicKey).ToArray(), null, 24);
                plainText  = _State.nonce.Concat(_State.sharedKey).Concat(plainText).ToArray();
                cipherText = PublicKeyBox.Create(plainText, nonce, _State.serverKey.PrivateKey, _State.clientKey);
            }
            else
            {
                cipherText = SecretBox.Create(plainText, _State.nonce, _State.sharedKey).Skip(16).ToArray();
            }

            byte[] packet = BitConverter.GetBytes(_PacketID).Reverse().Skip(2).Concat(BitConverter.GetBytes(cipherText.Length).Reverse().Skip(1)).Concat(BitConverter.GetBytes(unknown).Reverse().Skip(2)).Concat(cipherText).ToArray();
            _Socket.BeginSend(packet, 0, packet.Length, 0, SendCallback, _State);
        }
예제 #19
0
        public void SecretBox7()
        {
            byte[] k = new byte[SecretBox.KeySize];
            byte[] n = new byte[SecretBox.NonceSize];

            RandomNumberGenerator random = new RNGCryptoServiceProvider();

            int mlen;

            for (mlen = 0; mlen < 1000; ++mlen)
            {
                byte[] m  = new byte[mlen + SecretBox.ZeroSize];
                byte[] c  = new byte[mlen + SecretBox.ZeroSize];
                byte[] m2 = new byte[mlen + SecretBox.ZeroSize];

                random.GetBytes(k);
                random.GetBytes(n);
                random.GetBytes(m);

                Array.Clear(m, 0, SecretBox.ZeroSize);

                SecretBox secretBox = new SecretBox(k);

                secretBox.Box(c, m, n);
                secretBox.Open(m2, c, n);

                int i;
                for (i = 0; i < mlen + SecretBox.ZeroSize; ++i)
                {
                    Assert.AreEqual(m2[i], m[i]);
                }
            }
        }
예제 #20
0
        public static void DecryptPacket(Socket socket, ServerState state, byte[] packet)
        {
            var messageId     = BitConverter.ToInt32(new byte[2].Concat(packet.Take(2)).Reverse().ToArray(), 0);
            var payloadLength = BitConverter.ToInt32(new byte[1].Concat(packet.Skip(2).Take(3)).Reverse().ToArray(), 0);
            var unknown       = BitConverter.ToInt32(new byte[2].Concat(packet.Skip(2).Skip(3).Take(2)).Reverse().ToArray(), 0);
            var cipherText    = packet.Skip(2).Skip(3).Skip(2).ToArray();

            byte[] plainText;

            if (messageId == 10100)
            {
                plainText = cipherText;
            }
            else if (messageId == 10101)
            {
                state.clientKey = cipherText.Take(32).ToArray();
                var nonce = GenericHash.Hash(state.clientKey.Concat(state.serverKey.PublicKey).ToArray(), null, 24);
                cipherText              = cipherText.Skip(32).ToArray();
                plainText               = PublicKeyBox.Open(cipherText, nonce, state.serverKey.PrivateKey, state.clientKey);
                state.sessionKey        = plainText.Take(24).ToArray();
                state.clientState.nonce = plainText.Skip(24).Take(24).ToArray();
                plainText               = plainText.Skip(24).Skip(24).ToArray();
            }
            else
            {
                state.clientState.nonce = Utilities.Increment(Utilities.Increment(state.clientState.nonce));
                plainText = SecretBox.Open(new byte[16].Concat(cipherText).ToArray(), state.clientState.nonce,
                                           state.sharedKey);
            }
            Console.WriteLine("[UCR]    {0}" + Environment.NewLine + "{1}", PacketInfos.GetPacketName(messageId),
                              Utilities.BinaryToHex(packet.Take(7).ToArray()) + Utilities.BinaryToHex(plainText));
            ClientCrypto.EncryptPacket(state.clientState.socket, state.clientState, messageId, unknown, plainText);
        }
예제 #21
0
        public static void EncryptPacket(Socket socket, ServerState state, int messageId, int unknown, byte[] plainText)
        {
            byte[] cipherText;
            if (messageId == 20100)
            {
                cipherText = plainText;
            }
            else if (messageId == 20104)
            {
                var nonce =
                    GenericHash.Hash(
                        state.clientState.nonce.Concat(state.clientKey).Concat(state.serverKey.PublicKey).ToArray(),
                        null, 24);
                plainText  = state.nonce.Concat(state.sharedKey).Concat(plainText).ToArray();
                cipherText = PublicKeyBox.Create(plainText, nonce, state.serverKey.PrivateKey, state.clientKey);
            }
            else
            {
                cipherText = SecretBox.Create(plainText, state.nonce, state.sharedKey).Skip(16).ToArray();
            }
            var packet =
                BitConverter.GetBytes(messageId)
                .Reverse()
                .Skip(2)
                .Concat(BitConverter.GetBytes(cipherText.Length).Reverse().Skip(1))
                .Concat(BitConverter.GetBytes(unknown).Reverse().Skip(2))
                .Concat(cipherText)
                .ToArray();

            socket.BeginSend(packet, 0, packet.Length, 0, SendCallback, state);
        }
        public void VerifyLibhydrogenEncryptedMessageCanBeDecrypted()
        {
            var sb = new SecretBox();

            // Generate a key
            var key = new byte[SecretBox.KeyBytes];

            sb.GenerateKey(key);

            // Generate a message to encrypt
            var          message   = Encoding.UTF8.GetBytes("You are old Father William, the young man said");
            const int    messageId = 1;
            const string context   = "test";

            // Buffer to hold the ciphertext
            var ciphertext = new byte[sb.CalculateCiphertextLength(message.Length)];

            // Encrypt using libhydrogen
            var result = hydro_secretbox_encrypt(
                ciphertext, message, message.Length, messageId, context, key);

            // Verify that some ciphertext was generated
            Assert.That(ciphertext, Is.Not.All.Zero);
            Assert.That(result, Is.EqualTo(0));

            // Decrypt using SecretBox
            var decryptedMessage = new byte[message.Length];

            sb.Decrypt(decryptedMessage, ciphertext, ciphertext.Length, key, context, messageId);

            // Verify the decrypt was successful
            Assert.That(decryptedMessage, Is.EqualTo(message));
        }
예제 #23
0
        public async static Task <byte[]> ReadSecretMessage(Stream s, byte[] key, CancellationToken token = default)
        {
            var read = 0;

            byte[] header = new byte[4 + 24];
            while (read < header.Length)
            {
                read += await s.ReadAsync(header, read, header.Length - read, token);
            }

            var length = BitConverter.ToUInt32(header, 0);

            byte[] nonce = header.Skip(4).ToArray();

            if (length > MaxMessageLen)
            {
                throw new ArgumentOutOfRangeException($"Encrypted message specified a size of {length}, which is greater than the limit of {MaxMessageLen}");
            }

            byte[] ciphertext = new byte[length];
            read = 0;
            while (read < ciphertext.Length)
            {
                read += await s.ReadAsync(ciphertext, read, ciphertext.Length - read, token);
            }

            return(SecretBox.Open(ciphertext, nonce, key));
        }
예제 #24
0
        public void CalculateCipherTextLength()
        {
            const int messageLength  = 10;
            const int expectedLength = messageLength + HeaderBytes;
            var       sb             = new SecretBox();

            Assert.That(sb.CalculateCiphertextLength(messageLength), Is.EqualTo(expectedLength));
        }
예제 #25
0
        public void CalculateMessageLength()
        {
            const int ciphertextLength = 80;
            const int expectedLength   = ciphertextLength - HeaderBytes;
            var       sb = new SecretBox();

            Assert.That(sb.CalculateMessageLength(ciphertextLength), Is.EqualTo(expectedLength));
        }
예제 #26
0
 private static byte[] DecryptSecretSeed(byte[] seedBytes, byte[] keyHash)
 {
     byte[] nonceBytes  = new byte[24];
     byte[] cipherBytes = new byte[seedBytes.Length - nonceBytes.Length];
     Array.Copy(seedBytes, 0, nonceBytes, 0, nonceBytes.Length);
     Array.Copy(seedBytes, nonceBytes.Length, cipherBytes, 0, cipherBytes.Length);
     return(SecretBox.Open(cipherBytes, nonceBytes, keyHash));
 }
예제 #27
0
        public void VerifyDecryptFailsWithInvalidParameters()
        {
            // Encrypt a message
            var sb  = new SecretBox();
            var key = new byte[KeyBytes];

            sb.GenerateKey(key);
            var          message    = Encoding.UTF8.GetBytes("You are old Father William, the young man said");
            const int    messageId  = 1;
            const string context    = "test";
            var          ciphertext = new byte[sb.CalculateCiphertextLength(message.Length)];

            sb.Encrypt(ciphertext, message, message.Length, key, context, messageId);

            // Buffer to hold decrypted message
            var decryptedMessage = new byte[message.Length];

            // CiphertextLength is incorrect
            Assert.That(
                () => sb.Decrypt(decryptedMessage, ciphertext, HeaderBytes, key, context, messageId),
                Throws.TypeOf <CryptographicException>().With.Message.EqualTo("MAC check failed"));
            Assert.That(
                sb.TryDecrypt(decryptedMessage, ciphertext, HeaderBytes, key, context, messageId),
                Is.False);

            // MessageId is incorrect
            Assert.That(
                () => sb.Decrypt(decryptedMessage, ciphertext, ciphertext.Length, key, context, 2),
                Throws.TypeOf <CryptographicException>().With.Message.EqualTo("MAC check failed"));

            // Verify the decrypted message is not equal to the message, as a failed MAC check should not
            // leak the plaintext
            Assert.That(decryptedMessage, Is.Not.EqualTo(message));

            Assert.That(
                sb.TryDecrypt(decryptedMessage, ciphertext, ciphertext.Length, key, context, 2),
                Is.False);
            Assert.That(decryptedMessage, Is.Not.EqualTo(message));

            // Key is invalid
            key[0]++;
            Assert.That(
                () => sb.Decrypt(decryptedMessage, ciphertext, ciphertext.Length, key, context, messageId),
                Throws.TypeOf <CryptographicException>().With.Message.EqualTo("MAC check failed"));
            Assert.That(
                sb.TryDecrypt(decryptedMessage, ciphertext, ciphertext.Length, key, context, messageId),
                Is.False);
            key[0]--;

            // Ciphertext is invalid
            ciphertext[12]++;
            Assert.That(
                () => sb.Decrypt(decryptedMessage, ciphertext, ciphertext.Length, key, context, messageId),
                Throws.TypeOf <CryptographicException>().With.Message.EqualTo("MAC check failed"));
            Assert.That(
                sb.TryDecrypt(decryptedMessage, ciphertext, ciphertext.Length, key, context, messageId),
                Is.False);
        }
예제 #28
0
        public ConnectPacketData GetConnectPacket()
        {
            var connectPacketData = new ConnectPacketData
            {
                AddressType  = _connection.AddressType,
                DestPort     = _connection.DestPort,
                RouteCount   = (uint)_connection.ReturnRoutes.Length,
                ReturnRoutes = // TODO
            };

            if (_connection.AddressType == DestAddressType.DomainName)
            {
                connectPacketData.DestDomainName = _connection.DestDomainName;
            }
            else
            {
                connectPacketData.DestIpAddress = _connection.DestIpAddress;
            }

            var bytesToEncrypt = new byte[PacketContent.MaxSendDataLen + 27];

            var buffer = new WriteBuffer(bytesToEncrypt, 0);

            buffer.Write(_connection.UserId);
            buffer.Write(_connection.ConnectionId);
            buffer.Write(_connection.NextSequenceId);
            buffer.Write((byte)PacketDataType.Connect);
            buffer.Write(connectPacketData);
            var paddingLength = bytesToEncrypt.Length - buffer.TotalWritten;

            buffer.Write(new byte[paddingLength]);

            var route     = GenerateRoute(_possibleNodes);
            var encrypted = SecretBox.Create(bytesToEncrypt, OneNonce, route.Nodes[2].SymmetricKey);

            var destIdAndDataLen = new byte[10];

            buffer.Buffer = destIdAndDataLen;
            buffer.Write((ulong)0);
            buffer.Write((ushort)(encrypted.Length - 16));

            var innerPacketBytes = new byte[bytesToEncrypt.Length + 67];

            buffer.Buffer = innerPacketBytes;

            buffer.Write(route.Nodes[2].Node.Id);
            buffer.Write(route.Nodes[2].EphemeralPublicKey);
            buffer.Write((byte)(route.Nodes[2].SymmetricKey[31] & 1));
            buffer.Write(StreamEncryption.EncryptChaCha20(destIdAndDataLen, ZeroNonce, route.Nodes[2].SymmetricKey));
            buffer.Write(encrypted);

            encrypted = SecretBox.Create(encrypted, OneNonce, route.Nodes[2].SymmetricKey);

            var destId = new byte[8];

            buffer.Buffer = destId;
            buffer.Write(route.Nodes[1].Node.Id);
        }
예제 #29
0
        public void CalculateCipherTextLength_LessThanZero()
        {
            var sb = new SecretBox();

            Assert.That(
                () => sb.CalculateCiphertextLength(-3),
                Throws.ArgumentException.With.Message.EqualTo(
                    "messageLength must be greater than 0"));
        }
예제 #30
0
        public void CalculateMessageLength_Invalid(int ciphertextLength)
        {
            var sb = new SecretBox();

            Assert.That(
                () => sb.CalculateMessageLength(ciphertextLength),
                Throws.ArgumentException.With.Message.EqualTo(
                    $"ciphertextLength must be greater than {nameof(HeaderBytes)}"));
        }