/// <summary> /// Invokes the specified data. /// </summary> /// <typeparam name="TInput">The type of the input.</typeparam> /// <typeparam name="TOutput">The type of the output.</typeparam> /// <param name="uri">The URI.</param> /// <param name="data">The data.</param> /// <param name="rsaProvider">The RSA provider.</param> /// <param name="clientId">The client identifier.</param> /// <returns></returns> internal static TOutput Invoke <TInput, TOutput>(this Uri uri, ClassicVirtualSecuredRequestMessagePackage <TInput> data, RSACryptoServiceProvider rsaProvider, string clientId = null) { if (uri != null && data != null && rsaProvider != null) { try { var httpRequest = uri.CreateHttpWebRequest(HttpConstants.HttpMethod.Post); if (!string.IsNullOrWhiteSpace(clientId)) { httpRequest.SafeSetHttpHeader(VirtualSecuredTransferProtocolConstants.headerKey_ClientId, clientId); } var aesKeys = AesKeys.Create(); var aesProvider = aesKeys.CreateAesProvider(); var requestRawMessage = new VirtualSecuredRequestRawMessage { Data = Encoding.UTF8.GetBytes(data.ToJson(false)), SchemaVersion = _schemaVersion, SymmetricPrimaryKey = aesKeys.Key, SymmetricSecondaryKey = aesKeys.InitializationVector }; httpRequest.FillData(HttpConstants.HttpMethod.Post, PackToBytes(requestRawMessage, rsaProvider.GetRsaKeys().PublicKey, aesProvider)); var httpResult = httpRequest.ReadResponseAsBytes(); var responseBytes = httpResult.Body; var responseRawMessage = UnpackResponseFromBytes(responseBytes, rsaProvider, aesProvider); if (httpResult.HttpStatusCode.IsOK()) { return(Encoding.UTF8.GetString(responseRawMessage.Data).TryConvertJsonToObject <TOutput>()); } else { var exception = Encoding.UTF8.GetString(responseRawMessage.Data).TryConvertJsonToObject <ExceptionInfo>(); if (exception != null) { throw exception.ToException().Handle(new { uri, data }); } else { throw ExceptionFactory.CreateOperationException(new { uri, data }); } } } catch (Exception ex) { throw ex.Handle(new { uri, data }); } } return(default(TOutput)); }
/// <summary> /// Unpacks from bytes. /// </summary> /// <param name="requestBytes">The request bytes.</param> /// <param name="rsaProvider">The RSA provider.</param> /// <param name="aesProvider">The aes provider.</param> /// <returns></returns> public static VirtualSecuredRequestRawMessage UnpackRequestFromBytes(this byte[] requestBytes, RSACryptoServiceProvider rsaProvider, out RijndaelProvider aesProvider) { // Byte[] composition: [Schema Version]{1}[UTC Stamp]{4}[Encrypted Security Key Length Indication]{2+2}[Encrypted Security Key]{M+N}[Encrypted Body]{L}. aesProvider = null; try { rsaProvider.CheckNullObject(nameof(rsaProvider)); requestBytes.CheckNullOrEmptyCollection(nameof(requestBytes)); var result = new VirtualSecuredRequestRawMessage { // Index1 SchemaVersion = Convert.ToInt32(requestBytes[0]) }; var currentIndex = 1; // Index2 var stampBytes = requestBytes.Read(_stampIndicationByteLength, ref currentIndex); result.Stamp = GetUtcStampFromOffsetBytes(stampBytes); ValidateStamp(result.Stamp); // Index3 var primaryKeyLengthBytes = requestBytes.Read(_securityKeyIndicationByteLength, ref currentIndex); var primaryKeyLength = BitConverter.ToUInt16(primaryKeyLengthBytes, 0); var secondaryKeyLengthBytes = requestBytes.Read(_securityKeyIndicationByteLength, ref currentIndex); var secondaryKeyLength = BitConverter.ToUInt16(secondaryKeyLengthBytes, 0); // Index4 var primaryKeyBytes = requestBytes.Read(primaryKeyLength, ref currentIndex); result.SymmetricPrimaryKey = rsaProvider.Decrypt(primaryKeyBytes, true); var secondaryKeyBytes = requestBytes.Read(secondaryKeyLength, ref currentIndex); result.SymmetricSecondaryKey = secondaryKeyBytes == null ? null : rsaProvider.Decrypt(secondaryKeyBytes, true); aesProvider = new AesKeys { KeySize = dwKeySize, InitializationVector = result.SymmetricSecondaryKey, Key = result.SymmetricPrimaryKey }.CreateAesProvider(); // Index5 var dataBytes = requestBytes.SubArray(currentIndex); result.Data = aesProvider.DecryptAes(dataBytes); return(result); } catch (Exception ex) { throw ex.Handle(); } }
/// <summary> /// Packs to bytes. /// </summary> /// <param name="requestMessage">The request message.</param> /// <param name="rsaPublicKey">The RSA public key.</param> /// <param name="aesProvider">The aes provider.</param> /// <returns></returns> public static byte[] PackToBytes(this VirtualSecuredRequestRawMessage requestMessage, CryptoKey rsaPublicKey, RijndaelProvider aesProvider) { // Byte[] composition: [Schema Version]{1}[UTC Stamp]{4}[Encrypted Security Key Length Indication]{2+2}[Encrypted Security Key]{M+N}[Encrypted Body]{L}. try { rsaPublicKey.CheckNullObject(nameof(rsaPublicKey)); aesProvider.CheckNullObject(nameof(aesProvider)); requestMessage.CheckNullObject(nameof(requestMessage)); requestMessage.SymmetricPrimaryKey.CheckNullObject(nameof(requestMessage.SymmetricPrimaryKey)); requestMessage.Stamp.CheckNullObject(nameof(requestMessage.Stamp)); List <byte> result = new List <byte>(_packInitialCapacity) { // index1: version. Convert.ToByte(requestMessage.SchemaVersion) }; // index2: Stamp. result.AddRange(GetStampBytes(requestMessage.Stamp ?? DateTime.UtcNow)); // index3: Encrypted Security Key Length Indication. var encryptedSymmetricPrimaryKey = EncodingOrSecurityExtension.RsaEncrypt(requestMessage.SymmetricPrimaryKey, rsaPublicKey); var encryptedSymmetricSecondaryKey = (requestMessage.SymmetricSecondaryKey.ByteValue == null) ? null : EncodingOrSecurityExtension.RsaEncrypt(requestMessage.SymmetricSecondaryKey, rsaPublicKey); result.AddRange(BitConverter.GetBytes((UInt16)encryptedSymmetricPrimaryKey.Length)); result.AddRange(BitConverter.GetBytes((UInt16)encryptedSymmetricSecondaryKey.Length)); // index4: Encrypted Security Key result.AddRange(encryptedSymmetricPrimaryKey); if (encryptedSymmetricSecondaryKey.HasItem()) { result.AddRange(encryptedSymmetricSecondaryKey); } // index5: Encrypted content result.AddRange(aesProvider.EncryptAes(requestMessage.Data)); return(result.ToArray()); } catch (Exception ex) { throw ex.Handle(); } }