private string InternalBuild(string payload, string alg, string enc, JsonWebKey jsonWebKey, byte[] hmacKey = null) { var contentEncryptionKeyHandler = _cekHandlers.FirstOrDefault(e => e.AlgName == alg); var encEncryptionHandler = _encHandlers.FirstOrDefault(e => e.EncName == enc); if (contentEncryptionKeyHandler == null) { throw new JwtException(ErrorCodes.INTERNAL_ERROR, string.Format(ErrorMessages.UNKNOWN_ALG, alg)); } if (encEncryptionHandler == null) { throw new JwtException(ErrorCodes.INTERNAL_ERROR, string.Format(ErrorMessages.UNKNOWN_ENC, enc)); } var cek = BitHelper.GenerateRandomBytes(encEncryptionHandler.KeyLength); var encCEK = contentEncryptionKeyHandler.Encrypt(cek, jsonWebKey); var splittedCEK = BitHelper.SplitInHalf(cek); var iv = BitHelper.GenerateRandomBytes(128 /*encEncryptionHandler.KeyLength / 2*/); if (hmacKey == null) { hmacKey = splittedCEK.First(); } var key = splittedCEK.Last(); var cipherText = encEncryptionHandler.Encrypt(payload, key, iv); var protectedHeader = JsonConvert.SerializeObject(new JweHeader(alg, enc, jsonWebKey.Kid), Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); var protectedHeaderJson = protectedHeader.ToString(); var aad = Encoding.ASCII.GetBytes(Encoding.UTF8.GetBytes(protectedHeaderJson).Base64EncodeBytes()); var al = BitHelper.LongToBytes(aad.Length * 8); var hmacInput = BitHelper.Concat(aad, iv, cipherText, al); var hmacValue = encEncryptionHandler.BuildHash(hmacKey, hmacInput); var authTag = BitHelper.SplitInHalf(hmacValue).First(); var base64EncodedjweProtectedHeaderSerialized = protectedHeader.ToString().Base64Encode(); var base64EncodedJweEncryptedKey = encCEK.Base64EncodeBytes(); var base64EncodedIv = iv.Base64EncodeBytes(); var base64EncodedCipherText = cipherText.Base64EncodeBytes(); var base64EncodedAuthenticationTag = authTag.Base64EncodeBytes(); return(base64EncodedjweProtectedHeaderSerialized + "." + base64EncodedJweEncryptedKey + "." + base64EncodedIv + "." + base64EncodedCipherText + "." + base64EncodedAuthenticationTag); }