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._visualCrypt2Service.BinaryEncrypt(clearBytes, sha512PW64, 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); } var tlsEnvelope = new TLSEnvelope(dynamicSecret.PrivateKeyHint, dynamicSecret.DynamicPublicKeyId, dynamicSecret.DynamicPublicKey, encodeResponse.Result); return(tlsEnvelope); }
public static byte[] Serialize(this TLSEnvelope tlsEnvelope) { if (tlsEnvelope.TotalLength != TLSEnvelope.HeaderLength + tlsEnvelope.EncipheredPayload.Length) { throw new InvalidOperationException("Actual payload lenght does not match Length field."); } int serializedLength = TLSEnvelope.HeaderLength + tlsEnvelope.EncipheredPayload.Length; var serialized = new byte[serializedLength]; serialized[0] = TLSEnvelope.Version; serialized[1] = TLSEnvelope.MessageType; byte[] lenghtBytes = BitConverter.GetBytes(serializedLength); serialized[2] = lenghtBytes[0]; serialized[3] = lenghtBytes[1]; serialized[4] = lenghtBytes[2]; serialized[5] = lenghtBytes[3]; byte[] keyHint = BitConverter.GetBytes(tlsEnvelope.PrivateKeyHint); serialized[6 + 4] = keyHint[0]; serialized[7 + 4] = keyHint[1]; serialized[8 + 4] = keyHint[2]; serialized[9 + 4] = keyHint[3]; serialized[10 + 4] = keyHint[4]; serialized[11 + 4] = keyHint[5]; serialized[12 + 4] = keyHint[6]; serialized[13 + 4] = keyHint[7]; byte[] dynamicPublicKeyId = BitConverter.GetBytes(tlsEnvelope.DynamicPublicKeyId); serialized[14 + 4] = dynamicPublicKeyId[0]; serialized[15 + 4] = dynamicPublicKeyId[1]; serialized[16 + 4] = dynamicPublicKeyId[2]; serialized[17 + 4] = dynamicPublicKeyId[3]; serialized[18 + 4] = dynamicPublicKeyId[4]; serialized[19 + 4] = dynamicPublicKeyId[5]; serialized[20 + 4] = dynamicPublicKeyId[6]; serialized[21 + 4] = dynamicPublicKeyId[7]; Buffer.BlockCopy(tlsEnvelope.DynamicPublicKey, 0, serialized, 22 + 4, 32); Buffer.BlockCopy(tlsEnvelope.EncipheredPayload, 0, serialized, TLSEnvelope.HeaderLength, tlsEnvelope.EncipheredPayload.Length); var crc32 = Crc32.Compute(serialized); byte[] crc32Bytes = BitConverter.GetBytes(crc32); serialized[6] = crc32Bytes[0]; serialized[7] = crc32Bytes[1]; serialized[8] = crc32Bytes[2]; serialized[9] = crc32Bytes[3]; return(serialized); }
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._visualCrypt2Service.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 throwAwayPubKey = this._visualCrypt2Service.GenerateECKeyPair().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._visualCrypt2Service.BinaryEncrypt(clearBytes, sha512PW64, 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); } var tlsEnvelope = new TLSEnvelope(privateKeyHint, fakeDynamicPublicKeyID, throwAwayPubKey, encodeResponse.Result); return(tlsEnvelope); }
public async Task <TLSRequest> DecryptRequest(TLSEnvelope tlsEnvelope) { Guard.NotNull(tlsEnvelope); await this._publicMemberLock.WaitAsync(); try { var ar = new TLSRequest(); byte[] clientDynamicPrivateKey; this._server.DynamicPrivateDecryptionKeys.TryGetValue(tlsEnvelope.PrivateKeyHint, out clientDynamicPrivateKey); if (clientDynamicPrivateKey == null) { throw new Exception( "This should rarely happen. It means, the server has hinted me to private Key I no longer have."); } RemovePreviousKeys(tlsEnvelope.PrivateKeyHint); var dynamicSharedSecret = this._visualCrypt2Service.CalculateAndHashSharedSecret(clientDynamicPrivateKey, tlsEnvelope.DynamicPublicKey); Debug.WriteLine($"{this.MyId}: TLSDecrypt: PrivateKeyHint: {tlsEnvelope.PrivateKeyHint}"); // TLSAuthMode Combined byte[] authSecretBytes = this._server.AuthSecret; var symmetricKeyMaterial = ByteArrays.Concatenate(dynamicSharedSecret, authSecretBytes); // End TLSAuthMode Combined // TODO: make LRO optional! var lro = new LongRunningOperation(progress => { }, () => { }); var cipherV2 = VisualCrypt2Formatter.DissectVisualCryptBytes(tlsEnvelope.EncipheredPayload, lro.Context); var decryptResponse = this._visualCrypt2Service.BinaryDecrypt(cipherV2, new KeyMaterial64(symmetricKeyMaterial), lro.Context); var isIncomingKeyUnusable = false; if (!decryptResponse.IsSuccess) { // has the server just lost the dynamic keys? this._server.DynamicPrivateDecryptionKeys.TryGetValue(tlsEnvelope.PrivateKeyHint, out clientDynamicPrivateKey); if (clientDynamicPrivateKey == null) { throw new Exception( "This should rarely happen. It means, the server has hinted me to private Key I no longer have."); } dynamicSharedSecret = this._visualCrypt2Service.CalculateAndHashSharedSecret(clientDynamicPrivateKey, this._server.StaticPublicKey); authSecretBytes = new byte[32]; symmetricKeyMaterial = ByteArrays.Concatenate(dynamicSharedSecret, authSecretBytes); var decryptResponse2 = this._visualCrypt2Service.BinaryDecrypt(cipherV2, new KeyMaterial64(symmetricKeyMaterial), lro.Context); if (!decryptResponse2.IsSuccess) { throw new Exception("Decryption failed in all ways!"); } decryptResponse = decryptResponse2; Debug.WriteLine("Decryption succeded in Anonymous mode."); DoReset(); isIncomingKeyUnusable = true; } byte[] tlsDecryptedRequest = decryptResponse.Result.GetBytes(); ar.IsAuthenticated = true; ar.UserId = this._server.UserId; ar.CommandData = tlsDecryptedRequest; if (!isIncomingKeyUnusable) { Guard.NotNull(tlsEnvelope.DynamicPublicKey); if (tlsEnvelope.DynamicPublicKeyId == 0) { throw new ArgumentException("A dynamic public key must never have an ID of 0."); } this._server.LatestDynamicPublicKey = tlsEnvelope.DynamicPublicKey; this._server.LatestDynamicPublicKeyId = tlsEnvelope.DynamicPublicKeyId; } return(ar); } finally { this._publicMemberLock.Release(); } }
public TLSRequest TLSServerDecryptRequest(TLSEnvelope tlsEnvelope) { Guard.NotNull(tlsEnvelope); var ar = new TLSRequest(); byte[] serverPrivateKey; // static or dynamic if (tlsEnvelope.PrivateKeyHint == 0) // The client has used server's static public key to encrypt... { serverPrivateKey = this._serverPrivateKey; } // ... so we simple use the servers static private key else // tlsEnvelope.PrivateKeyHint is the number the server generated earlier { serverPrivateKey = GetServerDynamicPrivateKeyForUserByPrivateKeyHint(tlsEnvelope.PrivateKeyHint); } if (serverPrivateKey == null) { // we lost our dynamic private key b/c of a disk failure and we don't know who sent us what :-( return(null); } byte[] dynamicSharedSecret = this._visualCrypt2Service.CalculateAndHashSharedSecret(serverPrivateKey, tlsEnvelope.DynamicPublicKey); Debug.WriteLine($"{this.ServerId}: TLSDecrypt: PrivateKeyHint: {tlsEnvelope.PrivateKeyHint}"); // 'TLSAuthMode.Separate' byte[] symmetricKeyMaterial = ByteArrays.Concatenate(dynamicSharedSecret, new byte[32]); // no auth, we dont know who the user is // End 'TLSAuthMode.Separate' var lro = new LongRunningOperation(progress => { }, () => { }); var cipherV2 = VisualCrypt2Formatter.DissectVisualCryptBytes(tlsEnvelope.EncipheredPayload, lro.Context); var decryptResponse = this._visualCrypt2Service.BinaryDecrypt(cipherV2, new KeyMaterial64(symmetricKeyMaterial), lro.Context); if (!decryptResponse.IsSuccess) { throw new Exception(decryptResponse.Error); } byte[] tlsDecryptedRequest = decryptResponse.Result.GetBytes(); // 'TLSAuthMode.Separate' var authSecretFromMessage = new byte[32]; Buffer.BlockCopy(tlsDecryptedRequest, 0, authSecretFromMessage, 0, authSecretFromMessage.Length); // must be set even if the user is not authenticated for the case where a new identity is published right now. ar.UserId = Encoding.UTF8.GetString(tlsDecryptedRequest, 32, 10); // try authenticate var authSecret = GetAuthSecret(ar.UserId); if (authSecret != null) { if (ByteArrays.AreAllBytesEqual(authSecretFromMessage, authSecret)) { ar.IsAuthenticated = true; } } else { ar.IsAuthenticated = false; } var requestData = new byte[tlsDecryptedRequest.Length - 32 - 10]; Buffer.BlockCopy(tlsDecryptedRequest, 32 + 10, requestData, 0, requestData.Length); ar.CommandData = requestData; // End 'TLSAuthMode.Separate' if (ar.IsAuthenticated) { SaveIncomingDynamicPublicKey(ar.UserId, tlsEnvelope.DynamicPublicKey, tlsEnvelope.DynamicPublicKeyId); } return(ar); }