示例#1
0
        Compressed DecryptCommon(CipherV2 cipherV2, KeyMaterial64 keyMaterial64, LongRunningOperationContext context)
        {
            if (context == null)
            {
                context = new LongRunningOperation(progress => { }, () => { }).Context;
            }

            Guard.NotNull(new object[] { cipherV2, keyMaterial64 });
            EnsurePlatform();

            InputDerivedKey32 inputDerivedKey = cipherV2.RoundsExponent.Value == RoundsExponent.DontMakeRounds
                ? CreateDerivedKeyWithSHA256(cipherV2.IV16, keyMaterial64)
                : CreatePasswordDerivedKeyWithBCrypt(cipherV2.IV16, keyMaterial64, cipherV2.RoundsExponent, context);

            XDSSecAPIInternal.IVCache ivCache = cipherV2.RoundsExponent.Value == RoundsExponent.DontMakeRounds
                ? null
                : this._internal.CreateIVTable(cipherV2.IV16, cipherV2.RoundsExponent.Value);

            RandomKey32 randomKey = this._internal.AESDecryptRandomKeyWithPasswordDerivedKey(cipherV2, inputDerivedKey, ivCache, context);

            MAC16 decryptedMAC = this._internal.AESDecryptMAC(cipherV2, randomKey, ivCache, context);

            MAC16 actualMAC = CreateMAC(cipherV2, context);

            if (!actualMAC.GetBytes().SequenceEqual(decryptedMAC.GetBytes()))
            {
                throw new Exception(LocalizableStrings.MsgPasswordError);
            }

            PaddedData paddedData = this._internal.AESDecryptMessage(cipherV2, cipherV2.IV16, randomKey, ivCache, context);

            Compressed compressed = this._internal.RemovePadding(paddedData);

            return(compressed);
        }
示例#2
0
        public static byte[] EncryptClient(byte[] plaintextBytes, byte[] serverAuthPubKey, byte[] serverSessionPublicKey, byte[] singleClientPrivateKey)
        {
            if (plaintextBytes == null)
            {
                throw new ArgumentNullException(nameof(plaintextBytes));
            }
            if (serverAuthPubKey == null)
            {
                throw new ArgumentNullException(nameof(serverAuthPubKey));
            }
            if (serverSessionPublicKey == null)
            {
                throw new ArgumentNullException(nameof(serverSessionPublicKey));
            }
            if (singleClientPrivateKey == null)
            {
                throw new ArgumentNullException(nameof(singleClientPrivateKey));
            }

            var hashedSharedSecretBytes = VCL.Instance().CalculateAndHashSharedSecret(singleClientPrivateKey, serverSessionPublicKey);
            var authSecretBytes         = VCL.Instance().CalculateAndHashSharedSecret(singleClientPrivateKey, serverAuthPubKey);
            var keyMaterial64           = ToKeyMaterial64(hashedSharedSecretBytes, authSecretBytes);

            CipherV2 cipher = VCL.Instance().BinaryEncrypt(new Clearbytes(plaintextBytes), keyMaterial64, new RoundsExponent(RoundsExponent.DontMakeRounds), VCL.GetContext()).Result;

            return(VCL.Instance().BinaryEncodeXDSSec(cipher, VCL.GetContext()).Result);
        }
示例#3
0
        async Task EncryptAndSaveDeviceVaultKeyAsync(KeyMaterial64 masterRandomKey, KeyMaterial64 masterPassphraseKeyMaterial, LongRunningOperationContext context)
        {
            context.EncryptionProgress.Message = "Encrypting master random key";
            context.EncryptionProgress.Report(context.EncryptionProgress);
            CipherV2 encryptedMasterRandomKey = this.xdsCryptoService.BinaryEncrypt(new Clearbytes(masterRandomKey.GetBytes()), masterPassphraseKeyMaterial, new RoundsExponent(10), context).Result;

            byte[] encryptedMasterRandomKeyBytes = this.xdsCryptoService.BinaryEncodeXDSSec(encryptedMasterRandomKey, context).Result;
            await this.repo.WriteSpecialFile(MasterKeyFilename, encryptedMasterRandomKeyBytes);
        }
示例#4
0
        public static byte[] EncryptWithPassphrase(string passphrase, byte[] bytesToEncryt)
        {
            var context = GetContext();
            NormalizedPassword normalizedPassword           = Instance().NormalizePassword(passphrase).Result;
            KeyMaterial64      passwordDerivedkeyMaterial64 = Instance().HashPassword(normalizedPassword).Result;
            CipherV2           cipherV2 = Instance().BinaryEncrypt(new Clearbytes(bytesToEncryt), passwordDerivedkeyMaterial64, new RoundsExponent(RoundsExponent.DontMakeRounds), context).Result;
            var cipherV2Bytes           = Instance().BinaryEncodeXDSSec(cipherV2, context).Result;

            return(cipherV2Bytes);
        }
示例#5
0
        public byte[] DefaultDecrypt(byte[] cipherTextBytes, KeyMaterial64 keyMaterial64, LongRunningOperationContext context = null)
        {
            CipherV2 cipherV2 = XDSSecFormatter.DissectXDSSecBytes(cipherTextBytes, context);
            var      binaryDecryptResponse = BinaryDecrypt(cipherV2, keyMaterial64, context);

            if (!binaryDecryptResponse.IsSuccess)
            {
                throw new Exception(binaryDecryptResponse.Error);
            }
            return(binaryDecryptResponse.Result.GetBytes());
        }
        static CipherV2 DissectBytesToCipherV2(byte[] visualCryptBytes)
        {
            var version  = visualCryptBytes[0];
            var exponent = visualCryptBytes[1];
            var padding  = visualCryptBytes[2];

            if (version != CipherV2.Version)
            {
                throw CommonFormatException("Expected a version byte at index 0 of value '2'.");
            }

            if ((exponent > 31 || exponent < 4) && exponent != 0xff)
            {
                throw CommonFormatException("The value for the rounds exponent at index 1 is invalid.");
            }

            if (padding > 15)
            {
                throw CommonFormatException("The value at the padding byte at index 1 is invalid.");
            }


            var cipher = new CipherV2
            {
                PlaintextPadding = new PlaintextPadding(padding),
                RoundsExponent   = new RoundsExponent(exponent)
            };


            var iv16 = new byte[16];

            Buffer.BlockCopy(visualCryptBytes, 3, iv16, 0, 16);
            cipher.IV16 = new IV16(iv16);

            var macCipher = new byte[16];

            Buffer.BlockCopy(visualCryptBytes, 19, macCipher, 0, 16);
            cipher.MACCipher16 = new MACCipher16(macCipher);

            var randomKeyCipher = new byte[32];

            Buffer.BlockCopy(visualCryptBytes, 35, randomKeyCipher, 0, 32);
            cipher.RandomKeyCipher32 = new RandomKeyCipher32(randomKeyCipher);

            var cipherBytes = new byte[visualCryptBytes.Length - 67];

            Buffer.BlockCopy(visualCryptBytes, 67, cipherBytes, 0, cipherBytes.Length);
            cipher.MessageCipher = new MessageCipher(cipherBytes);

            return(cipher);
        }
示例#7
0
        public static byte[] DecryptWithPassphrase(string passphrase, byte[] bytesToDecrypt)
        {
            var context = GetContext();
            NormalizedPassword normalizedPassword           = Instance().NormalizePassword(passphrase).Result;
            KeyMaterial64      passwordDerivedkeyMaterial64 = Instance().HashPassword(normalizedPassword).Result;
            CipherV2           cipherV2 = Instance().BinaryDecodeXDSSec(bytesToDecrypt, context).Result;
            var response = Instance().BinaryDecrypt(cipherV2, passwordDerivedkeyMaterial64, context);

            if (response.IsSuccess)
            {
                return(response.Result.GetBytes());
            }
            return(null);
        }
        public static VisualCryptText CreateVisualCryptText(CipherV2 cipherV2)
        {
            Guard.NotNull(cipherV2);

            var visualCryptTextV2Bytes = ByteArrays.Concatenate(
                // len			Sum(len)		Start Index
                new[] { CipherV2.Version },                // 1			1				0
                new[] { cipherV2.RoundsExponent.Value },   // 1			2				1
                new[] { cipherV2.PlaintextPadding.Value }, // 1			3				2
                cipherV2.IV16.GetBytes(),                  // 16			19				3
                cipherV2.MACCipher16.GetBytes(),           // 16			35				19
                cipherV2.RandomKeyCipher32.GetBytes(),     // 32			67				35
                cipherV2.MessageCipher.GetBytes()          // len			67 + len		67
                );

            if (visualCryptTextV2Bytes.Length < HeaderLenght)
            {
                throw new Exception("Data cannot be shorter than the required header.");
            }

            var visualCryptTextV2Base64 = Base64Encoder.EncodeDataToBase64CharArray(visualCryptTextV2Bytes);

            var       sb          = new StringBuilder();
            const int breakAfter  = 74;
            var       charsInLine = 0;

            foreach (var c in VisualCryptSlashText)
            {
                sb.Append(c);
                if (++charsInLine != breakAfter)
                {
                    continue;
                }
                sb.Append(new[] { '\r', '\n' });
                charsInLine = 0;
            }

            foreach (var c in visualCryptTextV2Base64)
            {
                sb.Append(c == '/' ? '$' : c);
                if (++charsInLine != breakAfter)
                {
                    continue;
                }
                sb.Append(new[] { '\r', '\n' });
                charsInLine = 0;
            }

            return(new VisualCryptText(sb.ToString()));
        }
示例#9
0
 public MAC16 AESDecryptMAC(CipherV2 cipherV2, RandomKey32 randomKey, IVCache ivCache, LongRunningOperationContext context)
 {
     Guard.NotNull(new object[] { cipherV2, randomKey, context });
     byte[] macBytes;
     if (cipherV2.RoundsExponent.Value == RoundsExponent.DontMakeRounds)
     {
         macBytes = this._platform.ComputeAESRound(AESDir.Decrpyt, cipherV2.IV16.GetBytes(), cipherV2.MACCipher16.GetBytes(), randomKey.GetBytes());
     }
     else
     {
         context.EncryptionProgress.Message = LocalizableStrings.MsgDecryptingMAC;
         macBytes = ComputeAESWithRounds(AESDir.Decrpyt, cipherV2.IV16, cipherV2.MACCipher16.GetBytes(), randomKey.GetBytes(), cipherV2.RoundsExponent.Value, ivCache, context);
     }
     return(new MAC16(macBytes));
 }
示例#10
0
        public static byte[] Decrypt(byte[] cipherV2Bytes, byte[] publicKey, byte[] privateKey, byte[] privateAuthKey)
        {
            var hashedSharedSecretBytes = VCL.Instance().CalculateAndHashSharedSecret(privateKey, publicKey);
            var authSecretBytes         = VCL.Instance().CalculateAndHashSharedSecret(privateAuthKey, publicKey);
            var keyMaterial64           = ToKeyMaterial64(hashedSharedSecretBytes, authSecretBytes);

            CipherV2 cipherV2FromClient    = VCL.Instance().BinaryDecodeVisualCrypt(cipherV2Bytes, VCL.GetContext()).Result;
            var      binaryDecryptResponse = VCL.Instance().BinaryDecrypt(cipherV2FromClient, keyMaterial64, VCL.GetContext());

            if (!binaryDecryptResponse.IsSuccess && binaryDecryptResponse.Error == LocalizableStrings.MsgPasswordError)
            {
                return(null);
            }
            return(binaryDecryptResponse.Result.GetBytes());
        }
示例#11
0
        public void AESEncryptMACWithRandomKey(CipherV2 cipherV2, MAC16 mac, RandomKey32 randomKey, IVCache ivCache, LongRunningOperationContext context)
        {
            Guard.NotNull(new object[] { cipherV2, mac, randomKey, context });

            if (cipherV2.RoundsExponent.Value == RoundsExponent.DontMakeRounds)
            {
                Debug.Assert(ivCache == null);
                cipherV2.MACCipher16 = new MACCipher16(this._platform.ComputeAESRound(AESDir.Encrypt, cipherV2.IV16.GetBytes(), mac.GetBytes(), randomKey.GetBytes()));
            }
            else
            {
                context.EncryptionProgress.Message = LocalizableStrings.MsgEncryptingMAC;
                cipherV2.MACCipher16 = new MACCipher16(ComputeAESWithRounds(AESDir.Encrypt, cipherV2.IV16, mac.GetBytes(), randomKey.GetBytes(), cipherV2.RoundsExponent.Value, ivCache, context));
            }
        }
示例#12
0
        /// <summary>
        /// Changes the master password by encrypting the master random key with a new password and updating the key file.
        /// </summary>
        /// <param name="currentMasterPassword">The current master password.</param>
        /// <param name="futureMasterPassword">The future master password.</param>
        /// <returns></returns>
        public async Task ChangeMasterPasswordAsync(string currentMasterPassword, string futureMasterPassword)
        {
            // Verify the user knows the current master password
            await TryLoadDecryptAndSetMasterRandomKeyAsync(currentMasterPassword, null);

            KeyMaterial64 futureMasterPasswordHash = CreateKeyMaterialFromPassphrase(futureMasterPassword);

            // get the current master random key in plaintext
            KeyMaterial64 currentPlaintextMasterRandomKey = this.xdsCryptoService.SymmetricKeyRepository.GetMasterRandomKey();

            // encrypt the current master random key for saving in the key file and write the file.
            CipherV2 encryptedMasterRandomKey = this.xdsCryptoService.BinaryEncrypt(new Clearbytes(currentPlaintextMasterRandomKey.GetBytes()), futureMasterPasswordHash, new RoundsExponent(10), null).Result;

            byte[] encryptedMasterRandomKeyBytes = this.xdsCryptoService.BinaryEncodeXDSSec(encryptedMasterRandomKey, null).Result;
            await this.repo.WriteSpecialFile(MasterKeyFilename, encryptedMasterRandomKeyBytes);
        }
示例#13
0
        public RandomKey32 AESDecryptRandomKeyWithPasswordDerivedKey(CipherV2 cipherV2, InputDerivedKey32 inputDerivedKey, IVCache ivCache, LongRunningOperationContext context)
        {
            Guard.NotNull(new object[] { cipherV2, inputDerivedKey, context });

            byte[] randomKeyBytes;
            if (cipherV2.RoundsExponent.Value == RoundsExponent.DontMakeRounds)
            {
                randomKeyBytes = this._platform.ComputeAESRound(AESDir.Decrpyt, cipherV2.IV16.GetBytes(), cipherV2.RandomKeyCipher32.GetBytes(), inputDerivedKey.GetBytes());
            }
            else
            {
                context.EncryptionProgress.Message = LocalizableStrings.MsgDecryptingRandomKey;
                randomKeyBytes = ComputeAESWithRounds(AESDir.Decrpyt, cipherV2.IV16, cipherV2.RandomKeyCipher32.GetBytes(), inputDerivedKey.GetBytes(), cipherV2.RoundsExponent.Value, ivCache, context);
            }
            return(new RandomKey32(randomKeyBytes));
        }
示例#14
0
        public PaddedData AESDecryptMessage(CipherV2 cipherV2, IV16 iv16, RandomKey32 randomKey, IVCache ivCache, LongRunningOperationContext context)
        {
            Guard.NotNull(new object[] { cipherV2, iv16, randomKey, context });

            byte[] paddedDataBytes;
            if (cipherV2.RoundsExponent.Value == RoundsExponent.DontMakeRounds)
            {
                paddedDataBytes = this._platform.ComputeAESRound(AESDir.Decrpyt, cipherV2.IV16.GetBytes(), cipherV2.MessageCipher.GetBytes(), randomKey.GetBytes());
            }
            else
            {
                context.EncryptionProgress.Message = LocalizableStrings.MsgDecryptingMessage;
                paddedDataBytes = ComputeAESWithRounds(AESDir.Decrpyt, cipherV2.IV16, cipherV2.MessageCipher.GetBytes(), randomKey.GetBytes(), cipherV2.RoundsExponent.Value, ivCache, context);
            }
            return(new PaddedData(paddedDataBytes, cipherV2.PlaintextPadding));
        }
        public static byte[] CreateBinary(CipherV2 cipherV2)
        {
            Guard.NotNull(cipherV2);

            var visualCrypt2Bytes = ByteArrays.Concatenate(
                // len			Sum(len)		Start Index
                new[] { CipherV2.Version },                // 1			1				0
                new[] { cipherV2.RoundsExponent.Value },   // 1			2				1
                new[] { cipherV2.PlaintextPadding.Value }, // 1			3				2
                cipherV2.IV16.GetBytes(),                  // 16			19				3
                cipherV2.MACCipher16.GetBytes(),           // 16			35				19
                cipherV2.RandomKeyCipher32.GetBytes(),     // 32			67				35
                cipherV2.MessageCipher.GetBytes()          // len			67 + len		67
                );

            return(visualCrypt2Bytes);
        }
示例#16
0
        public Response <byte[]> BinaryEncodeXDSSec(CipherV2 cipherV2, LongRunningOperationContext context)
        {
            var response = new Response <byte[]>();

            try
            {
                Guard.NotNull(cipherV2);
                EnsurePlatform();
                context?.CancellationToken.ThrowIfCancellationRequested();
                response.Result = XDSSecFormatter.CreateBinary(cipherV2);
                response.SetSuccess();
            }
            catch (Exception e)
            {
                response.SetError(e);
            }
            return(response);
        }
示例#17
0
        public Response <XDSSecText> EncodeXDSSec(CipherV2 cipherV2)
        {
            var response = new Response <XDSSecText>();

            try
            {
                Guard.NotNull(cipherV2);
                EnsurePlatform();

                response.Result = XDSSecFormatter.CreateXDSSecText(cipherV2);
                response.SetSuccess();
            }
            catch (Exception e)
            {
                response.SetError(e);
            }
            return(response);
        }
示例#18
0
        public Response <Clearbytes> BinaryDecrypt(CipherV2 cipherV2, KeyMaterial64 keyMaterial64, LongRunningOperationContext context)
        {
            var response = new Response <Clearbytes>();

            try
            {
                Compressed compressed = DecryptCommon(cipherV2, keyMaterial64, context);

                Clearbytes cleartext = this._internal.DecompressBytes(compressed);

                response.Result = cleartext;
                response.SetSuccess();
            }
            catch (Exception e)
            {
                response.SetError(e);
            }
            return(response);
        }
示例#19
0
        MAC16 CreateMAC(CipherV2 cipherV2, LongRunningOperationContext context)
        {
            // Create the MAC only for items that, while decrypting, have not been used up to this point but do include the version.
            var securables = ByteArrays.Concatenate(cipherV2.MessageCipher.GetBytes(), new[] { cipherV2.PlaintextPadding.Value },
                                                    new[] { CipherV2.Version });

            // See e.g. http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf Chapter 7 for hash truncation.
            byte[] truncatedHash = new byte[16];
            if (cipherV2.RoundsExponent.Value == RoundsExponent.DontMakeRounds)
            {
                var sha256 = this._platform.ComputeSHA256(securables);
                Buffer.BlockCopy(sha256, 0, truncatedHash, 0, 16);
            }
            else
            {
                context.EncryptionProgress.Message = LocalizableStrings.MsgCalculatingMAC;
                var bCrypt24 = BCrypt.CreateHash(cipherV2.IV16, securables, cipherV2.RoundsExponent.Value, context);
                Buffer.BlockCopy(bCrypt24.GetBytes(), 0, truncatedHash, 0, 16);
            }
            return(new MAC16(truncatedHash));
        }
        public static byte[] CreateBinaryDH(CipherV2 cipherV2)
        {
            Guard.NotNull(cipherV2);
            var randomKeyCipher32Placeholder = new byte[32];

            randomKeyCipher32Placeholder[0] = 1; // insert a bit so that the SecureBytes validation does not throw.
            cipherV2.RandomKeyCipher32      = new RandomKeyCipher32(randomKeyCipher32Placeholder);

            var visualCrypt2Bytes = ByteArrays.Concatenate(
                // len			Sum(len)		Start Index
                new[] { CipherV2.Version },                // 1			1				0
                new[] { cipherV2.RoundsExponent.Value },   // 1			2				1
                new[] { cipherV2.PlaintextPadding.Value }, // 1			3				2
                cipherV2.IV16.GetBytes(),                  // 16			19				3
                cipherV2.MACCipher16.GetBytes(),           // 16			35				19
                cipherV2.RandomKeyCipher32.GetBytes(),     // 32			67				35
                cipherV2.MessageCipher.GetBytes()          // len			67 + len		67
                );

            return(visualCrypt2Bytes);
        }
示例#21
0
        CipherV2 EncryptCommon(KeyMaterial64 keyMaterial64, RoundsExponent roundsExponent, LongRunningOperationContext context,
                               Compressed compressed)
        {
            if (context == null)
            {
                context = new LongRunningOperation(progress => { }, () => { }).Context;
            }

            if (this._log)
            {
                Debug.WriteLine("KeyMaterial64:");
                Debug.WriteLine(keyMaterial64.GetBytes().ToHexView(false));
            }

            if (this._log)
            {
                Debug.WriteLine("Compressed:");
                Debug.WriteLine(compressed.GetBytes().ToHexView(false));
            }

            PaddedData paddedData = this._internal.ApplyRandomPadding(compressed);

            if (this._log)
            {
                Debug.WriteLine("PaddedData:");
                Debug.WriteLine(paddedData.GetBytes().ToHexView(false));

                Debug.WriteLine("PlainTextPadding:");
                Debug.WriteLine(paddedData.PlaintextPadding);
            }

            IV16 iv = new IV16(this._platform.GenerateRandomBytes(16));

            if (this._log)
            {
                Debug.WriteLine("IV16:");
                Debug.WriteLine(iv.GetBytes().ToHexView(false));
            }

            InputDerivedKey32 inputDerivedKey = roundsExponent.Value == RoundsExponent.DontMakeRounds
                ? CreateDerivedKeyWithSHA256(iv, keyMaterial64)
                : CreatePasswordDerivedKeyWithBCrypt(iv, keyMaterial64, roundsExponent, context);

            if (this._log)
            {
                Debug.WriteLine("InputDerivedKey32:");
                Debug.WriteLine(inputDerivedKey.GetBytes().ToHexView(false));
            }

            RandomKey32 randomKey = new RandomKey32(this._platform.GenerateRandomBytes(32));

            if (this._log)
            {
                Debug.WriteLine("RandomKey32:");
                Debug.WriteLine(randomKey.GetBytes().ToHexView(false));
            }

            XDSSecAPIInternal.IVCache ivCache = roundsExponent.Value == RoundsExponent.DontMakeRounds
                ? null
                : this._internal.CreateIVTable(iv, roundsExponent.Value);

            var cipherV2 = new CipherV2 {
                RoundsExponent = roundsExponent, IV16 = iv
            };

            this._internal.AESEncryptRandomKeyWithInputDerivedKey(inputDerivedKey, randomKey, cipherV2, ivCache, context);
            if (this._log)
            {
                Debug.WriteLine("RandomKeyCipher32:");
                Debug.WriteLine(cipherV2.RandomKeyCipher32.GetBytes().ToHexView(false));
            }

            this._internal.AESEncryptMessageWithRandomKey(paddedData, randomKey, cipherV2, ivCache, context);
            if (this._log)
            {
                Debug.WriteLine("MessageCipher:");
                Debug.WriteLine(cipherV2.MessageCipher.GetBytes().ToHexView(false));
            }

            MAC16 mac = CreateMAC(cipherV2, context);

            if (this._log)
            {
                Debug.WriteLine("MAC16:");
                Debug.WriteLine(mac.GetBytes().ToHexView(false));
            }

            this._internal.AESEncryptMACWithRandomKey(cipherV2, mac, randomKey, ivCache, context);
            if (this._log)
            {
                Debug.WriteLine("MACCipher16:");
                Debug.WriteLine(cipherV2.MACCipher16.GetBytes().ToHexView(false));
            }
            return(cipherV2);
        }
示例#22
0
        public void AESEncryptMessageWithRandomKey(PaddedData paddedData, RandomKey32 randomKey, CipherV2 cipherV2, IVCache ivCache, LongRunningOperationContext context)
        {
            Guard.NotNull(new object[] { paddedData, randomKey, cipherV2, context });

            cipherV2.PlaintextPadding = paddedData.PlaintextPadding;

            if (cipherV2.RoundsExponent.Value == RoundsExponent.DontMakeRounds)
            {
                Debug.Assert(ivCache == null);
                cipherV2.MessageCipher = new MessageCipher(this._platform.ComputeAESRound(AESDir.Encrypt, cipherV2.IV16.GetBytes(), paddedData.GetBytes(), randomKey.GetBytes()));
            }
            else
            {
                context.EncryptionProgress.Message = LocalizableStrings.MsgEncryptingMessage;
                cipherV2.MessageCipher             = new MessageCipher(ComputeAESWithRounds(AESDir.Encrypt, cipherV2.IV16, paddedData.GetBytes(), randomKey.GetBytes(), cipherV2.RoundsExponent.Value, ivCache, context));
            }
        }
示例#23
0
        public void AESEncryptRandomKeyWithInputDerivedKey(InputDerivedKey32 inputDerivedKey, RandomKey32 randomKey, CipherV2 cipherV2, IVCache ivCache, LongRunningOperationContext context)
        {
            Guard.NotNull(new object[] { inputDerivedKey, randomKey, cipherV2, context });

            if (cipherV2.RoundsExponent.Value == RoundsExponent.DontMakeRounds)
            {
                Debug.Assert(ivCache == null);
                cipherV2.RandomKeyCipher32 = new RandomKeyCipher32(this._platform.ComputeAESRound(AESDir.Encrypt, cipherV2.IV16.GetBytes(), randomKey.GetBytes(), inputDerivedKey.GetBytes()));
            }
            else
            {
                context.EncryptionProgress.Message = LocalizableStrings.MsgEncryptingRandomKey;
                cipherV2.RandomKeyCipher32         = new RandomKeyCipher32(ComputeAESWithRounds(AESDir.Encrypt, cipherV2.IV16, randomKey.GetBytes(), inputDerivedKey.GetBytes(), cipherV2.RoundsExponent.Value, ivCache, context));
            }
        }
示例#24
0
        /// <summary>
        /// Fully decrypts a message of all types, both control and content messages (including images), if an end-to-en-encryption key can be determined.
        /// </summary>
        async Task <Message> TryDecryptMessageToFindSenderEnryptDecryptionKeyAndSaveIt(XMessage xmessage)
        {
            try
            {
                IReadOnlyList <Identity> contacts = await this.repo.GetAllContacts();

                var decryptedMessage = new Message
                {
                    // XMessage fields
                    RecipientId = "1", // drop my Id

                    TextCipher  = xmessage.TextCipher,
                    ImageCipher = xmessage.ImageCipher,

                    DynamicPublicKey   = xmessage.DynamicPublicKey,
                    DynamicPublicKeyId = xmessage.DynamicPublicKeyId,
                    PrivateKeyHint     = xmessage.PrivateKeyHint,

                    LocalMessageState = LocalMessageState.JustReceived,
                    SendMessageState  = SendMessageState.None,
                    Side = MessageSide.You,

                    // This is what we try to decrypt here
                    MessageType = MessageType.None,
                    SenderId    = null,
                };


                Response <CipherV2> decodeMetaResponse = this.ixdsCryptoService.BinaryDecodeXDSSec(xmessage.MetaCipher, null);
                if (!decodeMetaResponse.IsSuccess)
                {
                    return(null); // garbled, no chance, ignore!
                }
                foreach (Identity identity in contacts)
                {
                    GetE2EDecryptionKeyResult getE2EDecryptionKeyResult = await this.e2eRatchet.GetEndToEndDecryptionKeyAsync(identity.Id, xmessage.DynamicPublicKey, xmessage.PrivateKeyHint);

                    if (getE2EDecryptionKeyResult.E2EDecryptionKeyType == E2EDecryptionKeyType.UnavailableDynamicPrivateKey)
                    {
                        continue; // there was a privateKeyHint != 0 in the message, but the dynamic private key was not in the ratchet for user in the loop
                    }
                    KeyMaterial64 keyMaterial64 = getE2EDecryptionKeyResult.E2EDecryptionKeyMaterial;

                    var decryptMetaResponse = this.ixdsCryptoService.BinaryDecrypt(decodeMetaResponse.Result, keyMaterial64, null);
                    if (!decryptMetaResponse.IsSuccess)
                    {
                        continue;
                    }

                    await this.e2eRatchet.SaveIncomingDynamicPublicKeyOnSuccessfulDecryptionAsync(identity.Id, xmessage.DynamicPublicKey,
                                                                                                  xmessage.DynamicPublicKeyId);

                    XMessageMetaData metadata = decryptMetaResponse.Result.GetBytes().DeserializeMessageMetadata();

                    decryptedMessage.SenderId             = identity.Id;
                    decryptedMessage.MessageType          = metadata.MessageType;
                    decryptedMessage.SenderLocalMessageId = metadata.SenderLocalMessageId.ToString();


                    if (decryptedMessage.MessageType.IsReceipt())
                    {
                        return(decryptedMessage);
                    }

                    if (decryptedMessage.MessageType.IsContent())
                    {
                        if (decryptedMessage.MessageType == MessageType.Text || decryptedMessage.MessageType == MessageType.TextAndMedia || decryptedMessage.MessageType == MessageType.File)
                        {
                            // if the message has text, decrypt all text
                            var decodeTextResponse = this.ixdsCryptoService.BinaryDecodeXDSSec(xmessage.TextCipher, null);
                            if (!decodeTextResponse.IsSuccess)
                            {
                                return(null); // something is wrong, should have worked
                            }
                            var decrpytTextResponse = this.ixdsCryptoService.Decrypt(decodeTextResponse.Result, keyMaterial64, null);
                            if (!decrpytTextResponse.IsSuccess)
                            {
                                return(null); // something is wrong, should have worked
                            }
                            decryptedMessage.ThreadText = decrpytTextResponse.Result.Text;
                        }

                        if (decryptedMessage.MessageType == MessageType.Media || decryptedMessage.MessageType == MessageType.TextAndMedia || decryptedMessage.MessageType == MessageType.File)
                        {
                            // if the message has image content, decrypt the image content
                            var decodeImageResponse = this.ixdsCryptoService.BinaryDecodeXDSSec(xmessage.ImageCipher, null);
                            if (!decodeImageResponse.IsSuccess)
                            {
                                return(null); // something is wrong, should have worked
                            }
                            var decrpytImageResponse = this.ixdsCryptoService.BinaryDecrypt(decodeImageResponse.Result, keyMaterial64, null);
                            if (!decrpytImageResponse.IsSuccess)
                            {
                                return(null); // something is wrong, should have worked
                            }
                            decryptedMessage.ThreadMedia = decrpytImageResponse.Result.GetBytes();
                        }

                        decryptedMessage.EncryptedE2EEncryptionKey = this.ixdsCryptoService.DefaultEncrypt(keyMaterial64.GetBytes(), this.ixdsCryptoService.SymmetricKeyRepository.GetMasterRandomKey());
                        decryptedMessage.LocalMessageState         = LocalMessageState.Integrated;
                        await this.repo.AddMessage(decryptedMessage);
                    }
                    else
                    {
                        throw new Exception($"Invalid MessageType {decryptedMessage.MessageType}");
                    }

                    return(decryptedMessage);
                } // foreach



                // If we are here, assume it's a new contact's message or RESENT message:
                CipherV2      encryptedMetaData          = decodeMetaResponse.Result;
                KeyMaterial64 initialKey                 = this.e2eRatchet.GetInitialE2EDecryptionKey(xmessage.DynamicPublicKey);
                var           decryptInitialMetaResponse = this.ixdsCryptoService.BinaryDecrypt(encryptedMetaData, initialKey, null);
                if (decryptInitialMetaResponse.IsSuccess)
                {
                    XMessageMetaData initialMessageMetadata =
                        decryptInitialMetaResponse.Result.GetBytes().DeserializeMessageMetadata();
                    var incomingPublicKey = initialMessageMetadata.SenderPublicKey;

                    // If we received several resent messages, the first from that incoming contact has already produced that contact:
                    var  contact           = contacts.SingleOrDefault(c => ByteArrays.AreAllBytesEqual(c.StaticPublicKey, incomingPublicKey));
                    bool isIncomingContact = false;

                    if (contact == null)
                    {
                        // Create new contact and save it to make the ratchet work normally
                        isIncomingContact = true;
                        var date            = DateTime.UtcNow;
                        var incomingContact = new Identity
                        {
                            Id = Guid.NewGuid().ToString(),
                            StaticPublicKey = incomingPublicKey,
                            ContactState    = ContactState.Valid,
                            Name            = "Anonymous",
                            FirstSeenUtc    = date,
                            LastSeenUtc     = date
                        };

                        await this.repo.AddContact(incomingContact);

                        contact = incomingContact;
                    }



                    await this.e2eRatchet.SaveIncomingDynamicPublicKeyOnSuccessfulDecryptionAsync(contact.Id, xmessage.DynamicPublicKey,
                                                                                                  xmessage.DynamicPublicKeyId);

                    // add metadata to message
                    decryptedMessage.SenderId             = contact.Id;
                    decryptedMessage.MessageType          = initialMessageMetadata.MessageType;
                    decryptedMessage.SenderLocalMessageId = initialMessageMetadata.SenderLocalMessageId.ToString();

                    if (decryptedMessage.MessageType.IsContent())
                    {
                        var success = true;

                        GetE2EDecryptionKeyResult getE2EDecryptionKeyResult = await this.e2eRatchet.GetEndToEndDecryptionKeyAsync(contact.Id, xmessage.DynamicPublicKey, xmessage.PrivateKeyHint);

                        KeyMaterial64 keyMaterial64 = getE2EDecryptionKeyResult.E2EDecryptionKeyMaterial;
                        await this.e2eRatchet.GetEndToEndDecryptionKeyAsync(contact.Id, xmessage.DynamicPublicKey, xmessage.PrivateKeyHint);

                        if (decryptedMessage.MessageType == MessageType.Text || decryptedMessage.MessageType == MessageType.TextAndMedia)
                        {
                            // if the message has text, decrypt all text
                            var decodeTextResponse = this.ixdsCryptoService.BinaryDecodeXDSSec(xmessage.TextCipher, null);
                            if (!decodeTextResponse.IsSuccess)
                            {
                                success = false; // something is wrong, should have worked
                            }
                            else
                            {
                                var decrpytTextResponse = this.ixdsCryptoService.Decrypt(decodeTextResponse.Result, keyMaterial64, null);
                                if (!decrpytTextResponse.IsSuccess)
                                {
                                    success = false; // something is wrong, should have worked
                                }
                                else
                                {
                                    decryptedMessage.ThreadText = decrpytTextResponse.Result.Text;
                                }
                            }
                        }

                        if (decryptedMessage.MessageType == MessageType.Media || decryptedMessage.MessageType == MessageType.TextAndMedia)
                        {
                            // if the message has image content, decrypt the image content
                            var decodeImageResponse = this.ixdsCryptoService.BinaryDecodeXDSSec(xmessage.ImageCipher, null);
                            if (!decodeImageResponse.IsSuccess)
                            {
                                success = false; // something is wrong, should have worked
                            }
                            else
                            {
                                var decrpytImageResponse = this.ixdsCryptoService.BinaryDecrypt(decodeImageResponse.Result, keyMaterial64, null);
                                if (!decrpytImageResponse.IsSuccess)
                                {
                                    success = false; // something is wrong, should have worked
                                }
                                else
                                {
                                    decryptedMessage.ThreadMedia = decrpytImageResponse.Result.GetBytes();
                                }
                            }
                        }

                        if (success)
                        {
                            decryptedMessage.EncryptedE2EEncryptionKey = this.ixdsCryptoService.DefaultEncrypt(keyMaterial64.GetBytes(), this.ixdsCryptoService.SymmetricKeyRepository.GetMasterRandomKey());
                            decryptedMessage.LocalMessageState         = LocalMessageState.Integrated;
                            await this.contactListManager.ChatWorker_ContactUpdateReceived(null, contact.Id);

                            await this.repo.AddMessage(decryptedMessage);

                            return(decryptedMessage);
                        }
                        else
                        {
                            if (isIncomingContact)
                            {
                                await this.repo.DeleteContacts(new[] { contact.Id }); // delete the just incoming contact if the was an error anyway.
                            }

                            return(null);
                        }
                    }
                    else
                    {
                        return(null);
                    }
                }

                // nope, resend request (I hope we don't loop here!)
                string networkPayloadHash = NetworkPayloadHash.ComputeAsGuidString(xmessage.SerializedPayload);
                if (!this._resendsRequested.Contains(networkPayloadHash))
                {
                    var response = await this.chatClient.UploadResendRequest(new XResendRequest { Id = networkPayloadHash, RecipientId = null });

                    if (response.IsSuccess)
                    {
                        this._resendsRequested.Add(networkPayloadHash);
                    }
                }
            }
            catch (Exception e)
            {
                this.logger.LogError(e.Message);
            }

            return(null);
        }