public TLSEnvelope TLSServerEncryptRequest(byte[] clearPacket, string recipientId) { byte[] authSecret = GetAuthSecret(recipientId); DynamicSecret dynamicSecret = GetDynamicSecretForEncryption(recipientId); Debug.WriteLine($"{this.ServerId}: TLSEncrypt: DynamicPublicKeyID: {dynamicSecret.DynamicPublicKeyId}, PrivateKeyHint: {dynamicSecret.PrivateKeyHint}."); // Concatenate = 'TLSAuthMode.Combined' byte[] symmetricKeyMaterial64 = ByteArrays.Concatenate(dynamicSecret.DynamicSharedSecret, authSecret); var lro = new LongRunningOperation(progress => { }, () => { }); var clearBytes = new Clearbytes(clearPacket); var sha512PW64 = new KeyMaterial64(symmetricKeyMaterial64); var method = new RoundsExponent(0xff); var encryptResponse = this.ixdsCryptoService.BinaryEncrypt(clearBytes, sha512PW64, method, lro.Context); if (!encryptResponse.IsSuccess) { throw new Exception(encryptResponse.Error); } var encodeResponse = this.ixdsCryptoService.BinaryEncodeXDSSec(encryptResponse.Result, lro.Context); if (!encodeResponse.IsSuccess) { throw new Exception(encodeResponse.Error); } var tlsEnvelope = new TLSEnvelope(dynamicSecret.PrivateKeyHint, dynamicSecret.DynamicPublicKeyId, dynamicSecret.DynamicPublicKey, encodeResponse.Result); return(tlsEnvelope); }
ChatWorker ChatWorker => this.dependencyInjection.ServiceProvider.Get <ChatWorker>(); // otherwise circular public async Task <Response> EncryptMessage(Message message, bool?isInitial = null) { var response = new Response(); try { var roundsExponent = new RoundsExponent(RoundsExponent.DontMakeRounds); var initialKeyResult = await this.e2ERatchet.GetE2EEncryptionKeyCommonAsync(message.RecipientId, isInitial); var keyMaterial = initialKeyResult.Item1; message.DynamicPublicKey = initialKeyResult.Item2; message.DynamicPublicKeyId = initialKeyResult.Item3; message.PrivateKeyHint = initialKeyResult.Item4; // I this is not null, either isInitial was true, or the ratchet was just initialized the first time for an added user's first message. var initialMetadataKeyMaterial = initialKeyResult.Item5; await Task.Run(() => EncryptWithStrategy(message, keyMaterial, roundsExponent, initialMetadataKeyMaterial)); response.SetSuccess(); } catch (Exception e) { response.SetError(e.Message); } return(response); }
void EncryptWithStrategy(Message message, KeyMaterial64 keyMaterial, RoundsExponent roundsExponent, KeyMaterial64 initialMetadataKeyMaterial) { XMessageMetaData messageMetadata = new XMessageMetaData { MessageType = message.MessageType }; switch (message.MessageType) { case MessageType.Text: message.TextCipher = EncryptTextToBytes(message.ThreadText, keyMaterial, roundsExponent); messageMetadata.SenderLocalMessageId = int.Parse(message.Id); break; case MessageType.Media: message.ImageCipher = this.ixdsCryptoService.DefaultEncrypt(message.ThreadMedia, keyMaterial); messageMetadata.SenderLocalMessageId = int.Parse(message.Id); break; case MessageType.TextAndMedia: case MessageType.File: message.TextCipher = EncryptTextToBytes(message.ThreadText, keyMaterial, roundsExponent); message.ImageCipher = this.ixdsCryptoService.DefaultEncrypt(message.ThreadMedia, keyMaterial); messageMetadata.SenderLocalMessageId = int.Parse(message.Id); break; case MessageType.DeliveryReceipt: case MessageType.ReadReceipt: messageMetadata.SenderLocalMessageId = int.Parse(message.SenderLocalMessageId); break; default: throw new Exception("Invalid MessageType"); } if (initialMetadataKeyMaterial != null) // initialMetadataKeyMaterial is only for resend requests { messageMetadata.SenderPublicKey = this.profileViewModel.PublicKey; message.MetaCipher = this.ixdsCryptoService.DefaultEncrypt(messageMetadata.SerializeCore(), initialMetadataKeyMaterial); } else { messageMetadata.SenderPublicKey = this.ixdsCryptoService.GetRandom(32).Result.X; message.MetaCipher = this.ixdsCryptoService.DefaultEncrypt(messageMetadata.SerializeCore(), keyMaterial); } if (!message.MessageType.IsReceipt()) { message.EncryptedE2EEncryptionKey = this.ixdsCryptoService.DefaultEncrypt(keyMaterial.GetBytes(), this.ixdsCryptoService.SymmetricKeyRepository.GetMasterRandomKey()); } }
byte[] EncryptTextToBytes(string clearText, KeyMaterial64 keyMaterial64, RoundsExponent roundsExponent) { var encryptResponse = this.ixdsCryptoService.Encrypt(new Cleartext(clearText), keyMaterial64, roundsExponent, null); if (!encryptResponse.IsSuccess) { throw new InvalidOperationException(encryptResponse.Error); } var encodeResponse = this.ixdsCryptoService.BinaryEncodeXDSSec(encryptResponse.Result, null); if (!encodeResponse.IsSuccess) { throw new InvalidOperationException(encodeResponse.Error); } return(encodeResponse.Result); }
public TLSEnvelope TLSServerEncryptRequestAnonymous(byte[] clearPacket, byte[] dynamicPublicKey, long dynamicPublicKeyID) { byte[] authSecret = new byte[32]; // we cannot create an authSecret based on the client's public key when we don't know who the client is. // we use the dynamicPublicKey and the server private key. var dynamicSharedSecret = this.ixdsCryptoService.CalculateAndHashSharedSecret(this._serverPrivateKey, dynamicPublicKey); // the hint to the clients privk for pubkey he sent long privateKeyHint = dynamicPublicKeyID; // and now we create a dynamic public key, just to fit the protocol, but not intended for use. var random = this.ixdsCryptoService.GetRandom(32).Result.X; var throwAwayPubKey = this.ixdsCryptoService.GenerateCurve25519KeyPairExact(random).Result.PublicKey; // and a fake id long fakeDynamicPublicKeyID = 9999; // use a realistic value, not 9999! Debug.WriteLine($"{this.ServerId}: TLSServerEncryptRequestAnonymous: FakeDynamicPublicKeyID: {fakeDynamicPublicKeyID}, PrivateKeyHint: {privateKeyHint}."); // Concatenate = 'TLSAuthMode.Dynamic' - THIS is anothe case! byte[] symmetricKeyMaterial64 = ByteArrays.Concatenate(dynamicSharedSecret, authSecret); // same as normally var lro = new LongRunningOperation(progress => { }, () => { }); var clearBytes = new Clearbytes(clearPacket); var sha512PW64 = new KeyMaterial64(symmetricKeyMaterial64); var method = new RoundsExponent(0xff); var encryptResponse = this.ixdsCryptoService.BinaryEncrypt(clearBytes, sha512PW64, method, lro.Context); if (!encryptResponse.IsSuccess) { throw new Exception(encryptResponse.Error); } var encodeResponse = this.ixdsCryptoService.BinaryEncodeXDSSec(encryptResponse.Result, lro.Context); if (!encodeResponse.IsSuccess) { throw new Exception(encodeResponse.Error); } var tlsEnvelope = new TLSEnvelope(privateKeyHint, fakeDynamicPublicKeyID, throwAwayPubKey, encodeResponse.Result); return(tlsEnvelope); }
public async Task <TLSEnvelope> EncryptRequest(byte[] clearPacket) { await this._publicMemberLock.WaitAsync(); try { DynamicSecret dynamicSecret = GetDynamicSecretForEncryption(); Debug.WriteLine( $"{this.MyId}: TLSEncrypt: DynamicPublicKeyID: {dynamicSecret.DynamicPublicKeyId}, PrivateKeyHint: {dynamicSecret.PrivateKeyHint}."); byte[] authSecret = this._server.AuthSecret; var securable = ByteArrays.Concatenate(authSecret, this._myIdBytes, clearPacket); var symmetricKeyMaterial64 = ByteArrays.Concatenate(dynamicSecret.DynamicSharedSecret, new byte[32]); var lro = new LongRunningOperation(progress => { }, () => { }); var clearBytes = new Clearbytes(securable); var keyMaterial64 = new KeyMaterial64(symmetricKeyMaterial64); var method = new RoundsExponent(0xff); var encryptResponse = this._visualCrypt2Service.BinaryEncrypt(clearBytes, keyMaterial64, method, lro.Context); if (!encryptResponse.IsSuccess) { throw new Exception(encryptResponse.Error); } var encodeResponse = this._visualCrypt2Service.BinaryEncodeVisualCrypt(encryptResponse.Result, lro.Context); if (!encodeResponse.IsSuccess) { throw new Exception(encodeResponse.Error); } return(new TLSEnvelope(dynamicSecret.PrivateKeyHint, dynamicSecret.DynamicPublicKeyId, dynamicSecret.DynamicPublicKey, encodeResponse.Result)); } finally { this._publicMemberLock.Release(); } }
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); }
public Response <CipherV2> Encrypt(Cleartext cleartext, KeyMaterial64 keyMaterial64, RoundsExponent roundsExponent, LongRunningOperationContext context) { var response = new Response <CipherV2>(); try { Guard.NotNull(new object[] { cleartext, keyMaterial64, roundsExponent }); EnsurePlatform(); Compressed compressed = this._internal.Compress(cleartext); var cipherV2 = EncryptCommon(keyMaterial64, roundsExponent, context, compressed); response.Result = cipherV2; response.SetSuccess(); } catch (Exception e) { response.SetError(e); } return(response); }
InputDerivedKey32 CreatePasswordDerivedKeyWithBCrypt(IV16 iv, KeyMaterial64 keyMaterial64, RoundsExponent roundsExponent, LongRunningOperationContext context) { var leftSHA512 = new byte[32]; var rightSHA512 = new byte[32]; Buffer.BlockCopy(keyMaterial64.GetBytes(), 0, leftSHA512, 0, 32); Buffer.BlockCopy(keyMaterial64.GetBytes(), 32, rightSHA512, 0, 32); context.EncryptionProgress.Message = LocalizableStrings.MsgProcessingKey; // Compute the left side on a ThreadPool thread var task = Task.Run(() => BCrypt.CreateHash(iv, leftSHA512, roundsExponent.Value, context)); // Compute the right side after dispatching the work for the right side BCrypt24 rightBCrypt = BCrypt.CreateHash(iv, rightSHA512, roundsExponent.Value, context); // Wait for the left side result task.Wait(context.CancellationToken); // Use the results var combinedHashes = ByteArrays.Concatenate(keyMaterial64.GetBytes(), task.Result.GetBytes(), rightBCrypt.GetBytes()); Debug.Assert(combinedHashes.Length == 64 + 24 + 24); var condensedHash = this._platform.ComputeSHA256(combinedHashes); return(new InputDerivedKey32(condensedHash)); }