/// <param name="ack1SdIsReady"> /// =true for SD in ACK2 /// =false for SD in ACK1 (since the SessionDescription is not initialized yet) /// </param> internal byte[] Encrypt(ICryptoLibrary cryptoLibrary, InviteRequestPacket req, InviteAck1Packet ack1, InviteSession session, bool ack1SdIsReady ) { BinaryProcedures.CreateBinaryWriter(out var ms, out var w); w.Write(Flags); UserCertificate.Encode(w, false); BinaryProcedures.EncodeIPEndPoint(w, DirectChannelEndPoint); NatBehaviour.Encode(w); DirectChannelToken32.Encode(w); w.Write((byte)SessionType); UserCertificateSignature.Encode(w); var bytesInLastBlock = (int)ms.Position % CryptoLibraries.AesBlockSize; if (bytesInLastBlock != 0) { var bytesRemainingTillFullAesBlock = CryptoLibraries.AesBlockSize - bytesInLastBlock; w.Write(cryptoLibrary.GetRandomBytes(bytesRemainingTillFullAesBlock)); } var plainTextSdData = ms.ToArray(); var encryptedSdData = new byte[plainTextSdData.Length]; #region key, iv BinaryProcedures.CreateBinaryWriter(out var ms2, out var w2); req.GetSharedSignedFields(w2); ack1.GetSharedSignedFields(w2, ack1SdIsReady); var iv = cryptoLibrary.GetHashSHA256(ms2.ToArray()).Take(16).ToArray(); ms2.Write(session.SharedInviteAckDhSecret, 0, session.SharedInviteAckDhSecret.Length); var aesKey = cryptoLibrary.GetHashSHA256(ms2.ToArray()); // here SHA256 is used as KDF, together with common fields from packets, including both ECDH public keys and timestamp #endregion cryptoLibrary.ProcessAesCbcBlocks(true, aesKey, iv, plainTextSdData, encryptedSdData); return(encryptedSdData); }
internal void DeriveKeys(ICryptoLibrary cryptoLibrary, byte[] sharedPingPongHmacKey, MessageStartPacket messageStart, byte[] directChannelSharedDhSecret) { if (Status != MessageSessionStatusCode.created) { throw new InvalidOperationException(); } BinaryProcedures.CreateBinaryWriter(out var msE, out var wE); messageStart.GetSignedFieldsForMessageHMAC(wE, false); wE.Write(sharedPingPongHmacKey); _iv = cryptoLibrary.GetHashSHA256(msE.ToArray()).Take(16).ToArray(); wE.Write(directChannelSharedDhSecret); _aesKey = cryptoLibrary.GetHashSHA256(msE.ToArray()); Status = MessageSessionStatusCode.inProgress; }
/// <param name="receivedFromUser">comes from local contact book. is null if it is contact invitation</param> internal static InviteSessionDescription Decrypt_Verify(ICryptoLibrary cryptoLibrary, byte[] encryptedSdData, InviteRequestPacket req, InviteAck1Packet ack1, bool ack1SdIsReady, InviteSession session, UserId receivedFromUserNullable, DateTime localTimeNowUtc ) { #region key, iv BinaryProcedures.CreateBinaryWriter(out var ms2, out var w2); req.GetSharedSignedFields(w2); ack1.GetSharedSignedFields(w2, ack1SdIsReady); var iv = cryptoLibrary.GetHashSHA256(ms2.ToArray()).Take(16).ToArray(); ms2.Write(session.SharedInviteAckDhSecret, 0, session.SharedInviteAckDhSecret.Length); var aesKey = cryptoLibrary.GetHashSHA256(ms2.ToArray()); // here SHA256 is used as KDF, together with common fields from packets, including both ECDH public keys and timestamp #endregion // decrypt var plainTextSdData = new byte[encryptedSdData.Length]; cryptoLibrary.ProcessAesCbcBlocks(false, aesKey, iv, encryptedSdData, plainTextSdData); var r = new InviteSessionDescription(); var reader = BinaryProcedures.CreateBinaryReader(plainTextSdData, 0); r.Flags = reader.ReadByte(); if ((r.Flags & FlagsMask_MustBeZero) != 0) { throw new NotImplementedException(); } r.UserCertificate = UserCertificate.Decode_AssertIsValidNow(reader, cryptoLibrary, receivedFromUserNullable, localTimeNowUtc); r.DirectChannelEndPoint = BinaryProcedures.DecodeIPEndPoint(reader); r.NatBehaviour = NatBehaviourModel.Decode(reader); r.DirectChannelToken32 = DirectChannelToken32.Decode(reader); r.SessionType = (SessionType)reader.ReadByte(); r.UserCertificateSignature = UserCertificateSignature.DecodeAndVerify(reader, cryptoLibrary, w => { req.GetSharedSignedFields(w); ack1.GetSharedSignedFields(w, ack1SdIsReady); r.WriteSignedFields(w); }, r.UserCertificate); return(r); }
void GetIVandKeys(int id, EncryptedFieldIds fieldId, out byte[] iv, out byte[] aesKey, out byte[] hmacKey) { BinaryProcedures.CreateBinaryWriter(out var ms, out var w); w.Write(id); w.Write((byte)fieldId); var sha256result = _cryptoLibrary.GetHashSHA256(ms.ToArray()); var preKey = _keyProvider.HsmOperation(sha256result); _cryptoLibrary.DeriveKeysRFC5869_32bytes(preKey, sha256result, out aesKey, out hmacKey); iv = sha256result.Take(16).ToArray(); }
double _distance_sumSqr; // 32 bytes of reg. public key: split into 16 dimensions of 2 bytes // euclidean distance public unsafe RegistrationIdDistance(ICryptoLibrary cryptoLibrary, RegistrationId rpk1, RegistrationId rpk2, int numberOfDimensions) { if (rpk1.CachedEd25519publicKeySha256 == null) { rpk1.CachedEd25519publicKeySha256 = cryptoLibrary.GetHashSHA256(rpk1.Ed25519publicKey); } var rpk1_ed25519publicKey_sha256 = rpk1.CachedEd25519publicKeySha256; if (rpk2.CachedEd25519publicKeySha256 == null) { rpk2.CachedEd25519publicKeySha256 = cryptoLibrary.GetHashSHA256(rpk2.Ed25519publicKey); } var rpk2_ed25519publicKey_sha256 = rpk2.CachedEd25519publicKeySha256; if (rpk1_ed25519publicKey_sha256.Length != rpk2_ed25519publicKey_sha256.Length) { throw new ArgumentException(); } _distance_sumSqr = 0; if (numberOfDimensions == 16) { fixed(byte *rpk1a = rpk1_ed25519publicKey_sha256, rpk2a = rpk2_ed25519publicKey_sha256) { ushort *rpk1aPtr = (ushort *)rpk1a, rpk2aPtr = (ushort *)rpk2a; int l = rpk1_ed25519publicKey_sha256.Length / 2; for (int i = 0; i < l; i++, rpk1aPtr++, rpk2aPtr++) { var d_i = VectorComponentRoutine(*rpk1aPtr, *rpk2aPtr); _distance_sumSqr += d_i * d_i; } } } else if (numberOfDimensions == 8) { fixed(byte *rpk1a = rpk1_ed25519publicKey_sha256, rpk2a = rpk2_ed25519publicKey_sha256) { uint *rpk1aPtr = (uint *)rpk1a, rpk2aPtr = (uint *)rpk2a; int l = rpk1_ed25519publicKey_sha256.Length / 4; for (int i = 0; i < l; i++, rpk1aPtr++, rpk2aPtr++) { var d_i = VectorComponentRoutine(*rpk1aPtr, *rpk2aPtr); _distance_sumSqr += d_i * d_i; } } } else if (numberOfDimensions == 4) { fixed(byte *rpk1a = rpk1_ed25519publicKey_sha256, rpk2a = rpk2_ed25519publicKey_sha256) { ulong *rpk1aPtr = (ulong *)rpk1a, rpk2aPtr = (ulong *)rpk2a; int l = rpk1_ed25519publicKey_sha256.Length / 8; for (int i = 0; i < l; i++, rpk1aPtr++, rpk2aPtr++) { var d_i = VectorComponentRoutine(*rpk1aPtr, *rpk2aPtr); _distance_sumSqr += d_i * d_i; } } } else if (numberOfDimensions == 2) { GetVectorValues_2(rpk1_ed25519publicKey_sha256, out var v1_0, out var v1_1); GetVectorValues_2(rpk2_ed25519publicKey_sha256, out var v2_0, out var v2_1); var d_0 = VectorComponentRoutine(v1_0, v2_0); var d_1 = VectorComponentRoutine(v1_1, v2_1); _distance_sumSqr += d_0 * d_0; _distance_sumSqr += d_1 * d_1; } else { throw new NotImplementedException(); } }
public static unsafe double[] GetVectorValues(ICryptoLibrary cryptoLibrary, RegistrationId rid, int numberOfDimensions) { var r = new double[numberOfDimensions]; if (rid.CachedEd25519publicKeySha256 == null) { rid.CachedEd25519publicKeySha256 = cryptoLibrary.GetHashSHA256(rid.Ed25519publicKey); } var rid_ed25519publicKey_sha256 = rid.CachedEd25519publicKeySha256; if (numberOfDimensions == 16) { fixed(byte *rpk1a = rid_ed25519publicKey_sha256) { ushort *rpk1aPtr = (ushort *)rpk1a; int l = rid_ed25519publicKey_sha256.Length / 2; for (int i = 0; i < l; i++, rpk1aPtr++) { r[i] = (double)(*rpk1aPtr) / UInt16.MaxValue; } } } else if (numberOfDimensions == 8) { fixed(byte *rpk1a = rid_ed25519publicKey_sha256) { uint *rpk1aPtr = (uint *)rpk1a; int l = rid_ed25519publicKey_sha256.Length / 4; for (int i = 0; i < l; i++, rpk1aPtr++) { r[i] = (double)(*rpk1aPtr) / UInt32.MaxValue; } } } else if (numberOfDimensions == 4) { fixed(byte *rpk1a = rid_ed25519publicKey_sha256) { ulong *rpk1aPtr = (ulong *)rpk1a; int l = rid_ed25519publicKey_sha256.Length / 8; for (int i = 0; i < l; i++, rpk1aPtr++) { r[i] = (double)(*rpk1aPtr) / ulong.MaxValue; } } } else if (numberOfDimensions == 2) { GetVectorValues_2(rid_ed25519publicKey_sha256, out var v0, out var v1); r[0] = v0; r[1] = v1; } else { throw new NotImplementedException(); } return(r); }
bool PassStatelessPoWfilter(ICcpRemoteEndpoint clientEndpoint, ClientHelloPacket0 packet)// packets processor thread // sends responses { switch (packet.StatelessProofOfWorkType) { case StatelessProofOfWorkType._2019_06: // verify size of PoW data if (packet.StatelessProofOfWorkData.Length < 12 || packet.StatelessProofOfWorkData.Length > 64) { throw new CcpBadPacketException(); } // verify datetime ("period") // return err code if time is wrong, with correct server's UTC time uint receivedTimeSec32; unsafe { fixed(byte *statelessProofOfWorkDataPtr = packet.StatelessProofOfWorkData) { fixed(byte *addressBytesPtr = clientEndpoint.AddressBytes) { receivedTimeSec32 = *((uint *)statelessProofOfWorkDataPtr); if (addressBytesPtr[0] != statelessProofOfWorkDataPtr[4] || addressBytesPtr[1] != statelessProofOfWorkDataPtr[5] || addressBytesPtr[2] != statelessProofOfWorkDataPtr[6] || addressBytesPtr[3] != statelessProofOfWorkDataPtr[7] ) { if (_config.RespondErrors) { RespondToHello0(clientEndpoint, ServerHello0Status.ErrorBadStatelessProofOfWork_BadSourceIp, packet.Cnonce0); } return(false); } } } } var localTimeSec32 = TimeSec32UTC; var diffSec = Math.Abs((int)unchecked (localTimeSec32 - receivedTimeSec32)); if (diffSec > _config.StatelessPoW_MaxClockDifferenceS) { // respond with error "try again with valid clock" - legitimate user has to get valid clock from some time server and synchronize itself with the server if (_config.RespondErrors) { RespondToHello0(clientEndpoint, ServerHello0Status.ErrorBadStatelessProofOfWork_BadClock, packet.Cnonce0); } return(false); } var hash = _cryptoLibrary.GetHashSHA256(packet.OriginalPacketPayload); // calculate hash, considering entire packet data (including stateless PoW result) // verify hash result if (!StatelessPowHashIsOK(hash)) { HandleBadStatelessPowPacket(clientEndpoint); // no response return(false); } // check if hash is unique var dataIsUnique = _recentUniquePowData.TryInputData(hash, localTimeSec32); if (dataIsUnique) { return(true); } else { // respond with error "try again with unique PoW data" if (_config.RespondErrors) { RespondToHello0(clientEndpoint, ServerHello0Status.ErrorTryAgainRightNowWithThisServer, packet.Cnonce0); } return(false); } default: throw new CcpBadPacketException(); } }