private static ECDsa LoadPrivateKey(string pem) { var reader = new PemReader(new StringReader(pem)); var keyPair = (AsymmetricCipherKeyPair)reader.ReadObject(); var p = (ECPrivateKeyParameters)keyPair.Private; var privKeyInt = p.D; var parameters = SecNamedCurves.GetByName("secp256r1"); var ecPoint = parameters.G.Multiply(privKeyInt); var privKeyX = ecPoint.Normalize().XCoord.ToBigInteger().ToByteArrayUnsigned(); var privKeyY = ecPoint.Normalize().YCoord.ToBigInteger().ToByteArrayUnsigned(); #if NETSTANDARD2_0 return(ECDsa.Create(new ECParameters { Curve = ECCurve.NamedCurves.nistP256, D = privKeyInt.ToByteArrayUnsigned(), Q = new ECPoint { X = privKeyX, Y = privKeyY } })); #else var x = EccKey.New(privKeyX, privKeyY, privKeyInt.ToByteArrayUnsigned()); var ecdsa = new ECDsaCng(x); return(ecdsa); #endif }
public void Derive128BitKey() { // https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-23#appendix-C //given byte[] bob_x = Base64Url.Decode("weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ"); byte[] bob_y = Base64Url.Decode("e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck"); byte[] bob_d = Base64Url.Decode("VEmDZpDXXK8p8N0Cndsxs924q6nS1RXFASRl6BfUqdw"); byte[] ephemeral_x = Base64Url.Decode("gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0"); byte[] ephemeral_y = Base64Url.Decode("SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps"); byte[] algorithmId = new byte[] { 0, 0, 0, 7, 65, 49, 50, 56, 71, 67, 77 }; byte[] partyUInfo = new byte[] { 0, 0, 0, 5, 65, 108, 105, 99, 101 }; byte[] partyVInfo = new byte[] { 0, 0, 0, 3, 66, 111, 98 }; byte[] suppPubInfo = new byte[] { 0, 0, 0, 128 }; //when byte[] key = ConcatKDF.DeriveKey(EccKey.New(ephemeral_x, ephemeral_y, usage: CngKeyUsages.KeyAgreement), EccKey.New(bob_x, bob_y, bob_d, usage: CngKeyUsages.KeyAgreement), 128, algorithmId, partyVInfo, partyUInfo, suppPubInfo); string test = Base64Url.Encode(key); //then Assert.Equal(test, "VqqN6vgjbSBcIijNcacQGg"); }
public virtual byte[] Unwrap(byte[] encryptedCek, object key, int cekSizeBits, IDictionary <string, object> header) { CngKey privateKey = null; if (key is Jwk jwk) { if (jwk.Kty == Jwk.KeyTypes.EC) { privateKey = jwk.CngKey(CngKeyUsages.KeyAgreement); } } privateKey = privateKey ?? Ensure.Type <CngKey>(key, "EcdhKeyManagement alg expects key to be of CngKey or Jwk types with kty='EC'."); Ensure.Contains(header, new[] { "epk" }, "EcdhKeyManagement algorithm expects 'epk' key param in JWT header, but was not found"); Ensure.Contains(header, new[] { algIdHeader }, "EcdhKeyManagement algorithm expects 'enc' header to be present in JWT header, but was not found"); var epk = (IDictionary <string, object>)header["epk"]; Ensure.Contains(epk, new[] { "x", "y", "crv" }, "EcdhKeyManagement algorithm expects 'epk' key to contain 'x','y' and 'crv' fields."); var x = Base64Url.Decode((string)epk["x"]); var y = Base64Url.Decode((string)epk["y"]); var externalPublicKey = EccKey.New(x, y, usage: CngKeyUsages.KeyAgreement); return(DeriveKey(header, cekSizeBits, externalPublicKey, privateKey)); }
private byte[] NewKey(int keyLength, object key, IDictionary <string, object> header) { CngKey recieverPubKey = null; if (key is Jwk jwk) { if (jwk.Kty == Jwk.KeyTypes.EC) { recieverPubKey = jwk.CngKey(CngKeyUsages.KeyAgreement); } } recieverPubKey = recieverPubKey ?? Ensure.Type <CngKey>(key, "EcdhKeyManagement alg expects key to be of CngKey or Jwk types with kty='EC'."); EccKey ephemeral = EccKey.Generate(recieverPubKey); IDictionary <string, object> epk = new Dictionary <string, object>(); epk["kty"] = "EC"; epk["x"] = Base64Url.Encode(ephemeral.X); epk["y"] = Base64Url.Encode(ephemeral.Y); epk["crv"] = ephemeral.Curve(); header["epk"] = epk; return(DeriveKey(header, keyLength, recieverPubKey, ephemeral.Key)); }
private static CngKey Ecc256Public(CngKeyUsages usage = CngKeyUsages.Signing) { byte[] x = { 4, 114, 29, 223, 58, 3, 191, 170, 67, 128, 229, 33, 242, 178, 157, 150, 133, 25, 209, 139, 166, 69, 55, 26, 84, 48, 169, 165, 67, 232, 98, 9 }; byte[] y = { 131, 116, 8, 14, 22, 150, 18, 75, 24, 181, 159, 78, 90, 51, 71, 159, 214, 186, 250, 47, 207, 246, 142, 127, 54, 183, 72, 72, 253, 21, 88, 53 }; byte[] d = { 42, 148, 231, 48, 225, 196, 166, 201, 23, 190, 229, 199, 20, 39, 226, 70, 209, 148, 29, 70, 125, 14, 174, 66, 9, 198, 80, 251, 95, 107, 98, 206 }; return(EccKey.New(x, y, usage: usage)); }
/// <summary> /// 解析token内的内容 /// </summary> /// <param name="accessToken">签权</param> /// <returns>Json对象</returns> public static JObject GetData(string accessToken) { var publicKey = EccKey.New(x, y, d); string json = Jose.JWT.Decode(accessToken, publicKey, JwsAlgorithm.ES256); return(JObject.Parse(json)); //string OpenId = Obj["openId"].ToString(); //return OpenId; }
/// <summary>JwkToCng</summary> /// <param name="jwk">JObject</param> /// <returns>CngKey(公開鍵)</returns> public static CngKey JwkToCng(Dictionary <string, string> jwk) { // 楕円曲線 // 不要 // 公開鍵の部分 return(EccKey.New( CustomEncode.FromBase64UrlString((string)jwk[JwtConst.x]), CustomEncode.FromBase64UrlString((string)jwk[JwtConst.y]))); }
/// <summary> /// 生成token /// </summary> /// <param name="name"></param> /// <returns></returns> public static string CreateAccessToken(string name) { var payload = new Dictionary <string, object>() { { "name", name }, { "exp", DateTime.Now.AddDays(3) } }; var privateKey = EccKey.New(x, y, d); return(Jose.JWT.Encode(payload, privateKey, JwsAlgorithm.ES256)); }
private byte[] NewKey(int keyLength, object key, IDictionary <string, object> header) { CngKey cngKey = Ensure.Type <CngKey>(key, "EcdhKeyManagement alg expects key to be of CngKey type.", new object[0]); EccKey eccKey = EccKey.Generate(cngKey); IDictionary <string, object> strs = new Dictionary <string, object>(); strs["kty"] = "EC"; strs["x"] = Base64Url.Encode(eccKey.X); strs["y"] = Base64Url.Encode(eccKey.Y); strs["crv"] = this.Curve(cngKey); header["epk"] = strs; return(this.DeriveKey(header, keyLength, cngKey, eccKey.Key)); }
public virtual byte[] Unwrap(byte[] encryptedCek, object key, int cekSizeBits, IDictionary <string, object> header) { CngKey cngKey = Ensure.Type <CngKey>(key, "EcdhKeyManagement alg expects key to be of CngKey type.", new object[0]); Ensure.Contains(header, new string[] { "epk" }, "EcdhKeyManagement algorithm expects 'epk' key param in JWT header, but was not found", new object[0]); Ensure.Contains(header, new string[] { this.algIdHeader }, "EcdhKeyManagement algorithm expects 'enc' header to be present in JWT header, but was not found", new object[0]); IDictionary <string, object> item = (IDictionary <string, object>)header["epk"]; Ensure.Contains(item, new string[] { "x", "y", "crv" }, "EcdhKeyManagement algorithm expects 'epk' key to contain 'x','y' and 'crv' fields.", new object[0]); byte[] numArray = Base64Url.Decode((string)item["x"]); byte[] numArray1 = Base64Url.Decode((string)item["y"]); CngKey cngKey1 = EccKey.New(numArray, numArray1, null, CngKeyUsages.KeyAgreement); return(this.DeriveKey(header, cekSizeBits, cngKey1, cngKey)); }
internal static void VerifyTokenSignature(string JwsJson, JObject jwk) { if ("EC".Equals(jwk["kty"].ToString())) { byte[] x = Base64Url.Decode(jwk["x"].ToString()); byte[] y = Base64Url.Decode(jwk["y"].ToString()); #if (NETCOREAPP2_1 || NETSTANDARD2_0) var publicKey = ECDsa.Create(new ECParameters { Curve = ECCurve.NamedCurves.nistP256, Q = new ECPoint { X = x, Y = y }, D = null }); var decoded = JWT.Decode(JwsJson, publicKey); #else CngKey cngKey = EccKey.New(x, y); var decoded = JWT.Decode(JwsJson, cngKey); #endif return; } else if ("RSA".Equals(jwk["kty"].ToString())) { byte[] n = Base64Url.Decode(jwk["n"].ToString()); byte[] e = Base64Url.Decode(jwk["e"].ToString()); using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider()) { RSAParameters rsaParameters = new RSAParameters { Exponent = e, Modulus = n }; RSA.ImportParameters(rsaParameters); JWT.Decode(JwsJson, RSA); return; } /*var publicKey = RsaKey.New(e, n); * var decoded = JWT.Decode(JwsJson, publicKey); * return;*/ } }
private byte[] NewKey(int keyLength, object key, IDictionary <string, object> header) { var recieverPubKey = Ensure.Type <CngKey>(key, "EcdhKeyManagement alg expects key to be of CngKey type."); EccKey ephemeral = EccKey.Generate(recieverPubKey); IDictionary <string, object> epk = new Dictionary <string, object>(); epk["kty"] = "EC"; epk["x"] = Base64Url.Encode(ephemeral.X); epk["y"] = Base64Url.Encode(ephemeral.Y); epk["crv"] = Curve(recieverPubKey); header["epk"] = epk; return(DeriveKey(header, keyLength, recieverPubKey, ephemeral.Key)); }
/// <summary> /// Elliptic Curve Diffie Hellman key agreement with AES Key Wrap using 256 bit key /// AES GCM Key Wrap Algorithm using 256 bit keys /// </summary> /// <param name="password"></param> /// <param name="plainText"></param> /// <returns></returns> public static string Encrypt(ECParameters exportParameters, string plainText) { // Claims see https://tools.ietf.org/html/rfc7519#section-4.1 var nonEncryptedHeaders = new Dictionary <string, object> { { "sub", "*****@*****.**" }, { "exp", 1300819380 } }; var publicKey = EccKey.New(exportParameters.Q.X, exportParameters.Q.Y, exportParameters.D, CngKeyUsages.KeyAgreement); // Not Implemented for NETSTANDARD 1.4 // https://github.com/dvsekhvalnov/jose-jwt/blob/e54de3bb706edf294053b4b86f0db47333d433ef/jose-jwt/crypto/ConcatKDF.cs#L43 var token = JWT.Encode(plainText, publicKey, JweAlgorithm.ECDH_ES, JweEncryption.A256GCM, extraHeaders: nonEncryptedHeaders); return(token); }
public virtual byte[] Unwrap(byte[] encryptedCek, object key, int cekSizeBits, IDictionary <string, object> header) { var privateKey = Ensure.Type <CngKey>(key, "EcdhKeyManagement alg expects key to be of CngKey type."); Ensure.Contains(header, new[] { "epk" }, "EcdhKeyManagement algorithm expects 'epk' key param in JWT header, but was not found"); Ensure.Contains(header, new[] { algIdHeader }, "EcdhKeyManagement algorithm expects 'enc' header to be present in JWT header, but was not found"); var jObject = (JObject)header["epk"]; var epk = jObject.ToObject <Dictionary <string, object> >(); Ensure.Contains(epk, new[] { "x", "y", "crv" }, "EcdhKeyManagement algorithm expects 'epk' key to contain 'x','y' and 'crv' fields."); var x = Base64Url.Decode((string)epk["x"]); var y = Base64Url.Decode((string)epk["y"]); var externalPublicKey = EccKey.New(x, y, usage: CngKeyUsages.KeyAgreement); return(DeriveKey(header, cekSizeBits, externalPublicKey, privateKey)); }
public void InvalidCurveAttack() { Skip.IfNot(RuntimeInformation.IsOSPlatform(OSPlatform.Windows), "This requires CNG, which is Windows Only."); // https://www.cs.bris.ac.uk/Research/CryptographySecurity/RWC/2017/nguyen.quan.pdf // Attack exploits some ECDH implementations which do not check // that ephemeral public key is on the private key's curve. byte[] x = Base64Url.Decode("weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ"); byte[] y = Base64Url.Decode("e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck"); byte[] d = Base64Url.Decode("VEmDZpDXXK8p8N0Cndsxs924q6nS1RXFASRl6BfUqdw"); var privateKey = EccKey.New(x, y, d, usage: CngKeyUsages.KeyAgreement); //JWT encrypted with attacker private key, which is equals to (reciever_pk mod 113) var attackMod113 = "eyJhbGciOiJFQ0RILUVTK0ExMjhLVyIsImVuYyI6IkExMjhDQkMtSFMyNTYiLCJlcGsiOnsia3R5IjoiRUMiLCJ4IjoiZ1RsaTY1ZVRRN3otQmgxNDdmZjhLM203azJVaURpRzJMcFlrV0FhRkpDYyIsInkiOiJjTEFuakthNGJ6akQ3REpWUHdhOUVQclJ6TUc3ck9OZ3NpVUQta2YzMEZzIiwiY3J2IjoiUC0yNTYifX0.qGAdxtEnrV_3zbIxU2ZKrMWcejNltjA_dtefBFnRh9A2z9cNIqYRWg.pEA5kX304PMCOmFSKX_cEg.a9fwUrx2JXi1OnWEMOmZhXd94-bEGCH9xxRwqcGuG2AMo-AwHoljdsH5C_kcTqlXS5p51OB1tvgQcMwB5rpTxg.72CHiYFecyDvuUa43KKT6w"; //JWT encrypted with attacker private key, which is equals to (reciever_pk mod 2447) var attackMod2447 = "eyJhbGciOiJFQ0RILUVTK0ExMjhLVyIsImVuYyI6IkExMjhDQkMtSFMyNTYiLCJlcGsiOnsia3R5IjoiRUMiLCJ4IjoiWE9YR1E5XzZRQ3ZCZzN1OHZDSS1VZEJ2SUNBRWNOTkJyZnFkN3RHN29RNCIsInkiOiJoUW9XTm90bk56S2x3aUNuZUprTElxRG5UTnc3SXNkQkM1M1ZVcVZqVkpjIiwiY3J2IjoiUC0yNTYifX0.UGb3hX3ePAvtFB9TCdWsNkFTv9QWxSr3MpYNiSBdW630uRXRBT3sxw.6VpU84oMob16DxOR98YTRw.y1UslvtkoWdl9HpugfP0rSAkTw1xhm_LbK1iRXzGdpYqNwIG5VU33UBpKAtKFBoA1Kk_sYtfnHYAvn-aes4FTg.UZPN8h7FcvA5MIOq-Pkj8A"; try { JWT.Decode(attackMod113, privateKey); Assert.True(false, "Should fail with CrytographicException"); } catch (CryptographicException e) { Console.WriteLine(e); } try { JWT.Decode(attackMod2447, privateKey); Assert.True(false, "Should fail with CrytographicException"); } catch (CryptographicException e) { Console.WriteLine(e); } }
/// <summary>JoseJwt</summary> private static void JoseJwt() { #region Variables #region Env OperatingSystem os = Environment.OSVersion; // https://github.com/dotnet/corefx/issues/29404#issuecomment-385287947 // *.pfxから証明書を開く場合、X509KeyStorageFlags.Exportableの指定が必要な場合がある。 // Linuxのキーは常にエクスポート可能だが、WindowsやMacOSでは必ずしもそうではない。 X509KeyStorageFlags x509KSF = 0; if (os.Platform == PlatformID.Win32NT) { x509KSF = X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable; } else //if (os.Platform == PlatformID.Unix) { x509KSF = X509KeyStorageFlags.DefaultKeySet; } #endregion #region Token string token = ""; IDictionary <string, object> headers = null; IDictionary <string, object> payload = null; payload = new Dictionary <string, object>() { { "sub", "*****@*****.**" }, { "exp", 1300819380 } }; #endregion #region Keys byte[] secretKey = null; byte[] x = null; byte[] y = null; byte[] d = null; X509Certificate2 publicX509Key = null; X509Certificate2 privateX509Key = null; RSA rsa = null; //DSA dsa = null; CngKey publicKeyOfCng = null; CngKey privateKeyOfCng = null; #endregion #endregion #region JWT #region Unsecured JWT // Creating Plaintext (unprotected) Tokens // https://github.com/dvsekhvalnov/jose-jwt#creating-plaintext-unprotected-tokens token = ""; token = JWT.Encode(payload, null, JwsAlgorithm.none); MyDebug.OutputDebugAndConsole("JwsAlgorithm.none", token); #endregion #region JWS (Creating signed Tokens) // https://github.com/dvsekhvalnov/jose-jwt#creating-signed-tokens #region HS-* family // HS256, HS384, HS512 // https://github.com/dvsekhvalnov/jose-jwt#hs--family secretKey = new byte[] { 164, 60, 194, 0, 161, 189, 41, 38, 130, 89, 141, 164, 45, 170, 159, 209, 69, 137, 243, 216, 191, 131, 47, 250, 32, 107, 231, 117, 37, 158, 225, 234 }; token = ""; token = JWT.Encode(payload, secretKey, JwsAlgorithm.HS256); Program.VerifyResult("JwsAlgorithm.HS256", token, secretKey); #endregion #region RS-* and PS-* family // RS256, RS384, RS512 and PS256, PS384, PS512 // https://github.com/dvsekhvalnov/jose-jwt#rs--and-ps--family // X509Certificate2 x509Certificate2 = new X509Certificate2(); privateX509Key = new X509Certificate2(Program.PrivateRsaX509Path, Program.PfxPassword, x509KSF); publicX509Key = new X509Certificate2(Program.PublicRsaX509Path, "", x509KSF); token = ""; #if NETCORE rsa = (RSA)privateX509Key.PrivateKey; #else // .net frameworkでは、何故かコレが必要。 rsa = (RSA)AsymmetricAlgorithmCmnFunc.CreateSameKeySizeSP(privateX509Key.PrivateKey); #endif token = JWT.Encode(payload, rsa, JwsAlgorithm.RS256); Program.VerifyResult("JwsAlgorithm.RS256", token, rsa); #endregion #region ES- * family // ES256, ES384, ES512 ECDSA signatures // https://github.com/dvsekhvalnov/jose-jwt#es---family x = new byte[] { 4, 114, 29, 223, 58, 3, 191, 170, 67, 128, 229, 33, 242, 178, 157, 150, 133, 25, 209, 139, 166, 69, 55, 26, 84, 48, 169, 165, 67, 232, 98, 9 }; y = new byte[] { 131, 116, 8, 14, 22, 150, 18, 75, 24, 181, 159, 78, 90, 51, 71, 159, 214, 186, 250, 47, 207, 246, 142, 127, 54, 183, 72, 72, 253, 21, 88, 53 }; d = new byte[] { 42, 148, 231, 48, 225, 196, 166, 201, 23, 190, 229, 199, 20, 39, 226, 70, 209, 148, 29, 70, 125, 14, 174, 66, 9, 198, 80, 251, 95, 107, 98, 206 }; if (os.Platform == PlatformID.Win32NT) { // https://github.com/dvsekhvalnov/jose-jwt/blob/master/jose-jwt/Security/Cryptography/EccKey.cs privateKeyOfCng = EccKey.New(x, y, d); publicKeyOfCng = EccKey.New(x, y); token = ""; token = JWT.Encode(payload, privateKeyOfCng, JwsAlgorithm.ES256); Program.VerifyResult("JwsAlgorithm.ES256", token, publicKeyOfCng); } else //if (os.Platform == PlatformID.Unix) { #if NETCORE ECParameters eCParameters = new ECParameters(); // Curve eCParameters.Curve = EccPublicKeyConverter.GetECCurveFromCrvString( EccPublicKeyConverter.GetCrvStringFromXCoordinate(x)); // x, y, d eCParameters.Q.X = x; eCParameters.Q.Y = y; eCParameters.D = d; ECDsaOpenSsl eCDsaOpenSsl = new ECDsaOpenSsl(eCParameters.Curve); eCDsaOpenSsl.ImportParameters(eCParameters); token = ""; token = JWT.Encode(payload, eCDsaOpenSsl, JwsAlgorithm.ES256); Program.VerifyResult("JwsAlgorithm.ES256", token, eCDsaOpenSsl); #endif } #if NETCORE || NET47 privateX509Key = new X509Certificate2(Program.PrivateECDsaX509Path, Program.PfxPassword); publicX509Key = new X509Certificate2(Program.PublicECDsaX509Path, ""); try { #if NETCORE if (os.Platform == PlatformID.Win32NT) { } else //if (os.Platform == PlatformID.Unix) { // ECCurveを分析してみる。 ECCurve eCCurve = ((ECDsaOpenSsl)privateX509Key.GetECDsaPrivateKey()).ExportExplicitParameters(true).Curve; MyDebug.OutputDebugAndConsole("Inspect ECCurve", ObjectInspector.Inspect(eCCurve)); } #endif token = ""; token = JWT.Encode(payload, privateX509Key.GetECDsaPrivateKey(), JwsAlgorithm.ES256); Program.VerifyResult("JwsAlgorithm.ES256", token, publicX509Key.GetECDsaPublicKey()); } catch (Exception ex) { MyDebug.OutputDebugAndConsole("JwsAlgorithm.ES256", ex.GetType().ToString() + ", " + ex.Message); } #endif #endregion #endregion #region JWE (Creating encrypted Tokens) // https://github.com/dvsekhvalnov/jose-jwt#creating-encrypted-tokens #region RSA-* key management family of algorithms // RSA-OAEP-256, RSA-OAEP and RSA1_5 key // https://github.com/dvsekhvalnov/jose-jwt#rsa--key-management-family-of-algorithms privateX509Key = new X509Certificate2(Program.PrivateRsaX509Path, Program.PfxPassword, x509KSF); publicX509Key = new X509Certificate2(Program.PublicRsaX509Path, "", x509KSF); // RSAES-PKCS1-v1_5 and AES_128_CBC_HMAC_SHA_256 token = ""; token = JWT.Encode(payload, publicX509Key.PublicKey.Key, JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256); Program.VerifyResult("JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256", token, privateX509Key.PrivateKey); // RSAES-OAEP and AES GCM try { token = ""; token = JWT.Encode(payload, publicX509Key.PublicKey.Key, JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM); Program.VerifyResult("JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM", token, privateX509Key.PrivateKey); } catch (Exception ex) { // Unhandled Exception: System.DllNotFoundException: Unable to load DLL 'bcrypt.dll' at ubunntu MyDebug.OutputDebugAndConsole("JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM", ex.GetType().ToString() + ", " + ex.Message); } #endregion #region Other key management family of algorithms secretKey = new byte[] { 164, 60, 194, 0, 161, 189, 41, 38, 130, 89, 141, 164, 45, 170, 159, 209, 69, 137, 243, 216, 191, 131, 47, 250, 32, 107, 231, 117, 37, 158, 225, 234 }; #region DIR direct pre-shared symmetric key family of algorithms // https://github.com/dvsekhvalnov/jose-jwt#dir-direct-pre-shared-symmetric-key-family-of-algorithms token = ""; token = JWT.Encode(payload, secretKey, JweAlgorithm.DIR, JweEncryption.A128CBC_HS256); Program.VerifyResult("JweAlgorithm.DIR, JweEncryption.A128CBC_HS256", token, secretKey); #endregion #region AES Key Wrap key management family of algorithms // AES128KW, AES192KW and AES256KW key management // https://github.com/dvsekhvalnov/jose-jwt#aes-key-wrap-key-management-family-of-algorithms token = ""; token = JWT.Encode(payload, secretKey, JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512); Program.VerifyResult("JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512", token, secretKey); #endregion #region AES GCM Key Wrap key management family of algorithms // AES128GCMKW, AES192GCMKW and AES256GCMKW key management // https://github.com/dvsekhvalnov/jose-jwt#aes-gcm-key-wrap-key-management-family-of-algorithms try { token = ""; token = JWT.Encode(payload, secretKey, JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512); Program.VerifyResult("JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512", token, secretKey); } catch (Exception ex) { // Unhandled Exception: System.DllNotFoundException: Unable to load DLL 'bcrypt.dll' at ubunntu MyDebug.OutputDebugAndConsole("JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512", ex.GetType().ToString() + ", " + ex.Message); } #endregion #region ECDH-ES and ECDH-ES with AES Key Wrap key management family of algorithms // ECDH-ES and ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW key management // https://github.com/dvsekhvalnov/jose-jwt#ecdh-es-and-ecdh-es-with-aes-key-wrap-key-management-family-of-algorithms try { x = new byte[] { 4, 114, 29, 223, 58, 3, 191, 170, 67, 128, 229, 33, 242, 178, 157, 150, 133, 25, 209, 139, 166, 69, 55, 26, 84, 48, 169, 165, 67, 232, 98, 9 }; y = new byte[] { 131, 116, 8, 14, 22, 150, 18, 75, 24, 181, 159, 78, 90, 51, 71, 159, 214, 186, 250, 47, 207, 246, 142, 127, 54, 183, 72, 72, 253, 21, 88, 53 }; publicKeyOfCng = EccKey.New(x, y, usage: CngKeyUsages.KeyAgreement); token = ""; token = JWT.Encode(payload, publicKeyOfCng, JweAlgorithm.ECDH_ES, JweEncryption.A256GCM); Program.VerifyResult("JweAlgorithm.ECDH_ES, JweEncryption.A256GCM", token, publicKeyOfCng); } catch (Exception ex) { // System.NotImplementedException: 'not yet' MyDebug.OutputDebugAndConsole("JweAlgorithm.ECDH_ES, JweEncryption.A256GCM", ex.GetType().ToString() + ", " + ex.Message); } #endregion #region PBES2 using HMAC SHA with AES Key Wrap key management family of algorithms token = ""; token = JWT.Encode(payload, "top secret", JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512); Program.VerifyResult("JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512", token, "top secret"); #endregion #endregion #endregion #endregion #region ELSE #region Additional utilities // https://github.com/dvsekhvalnov/jose-jwt#additional-utilities #region Adding extra headers // https://github.com/dvsekhvalnov/jose-jwt#adding-extra-headers headers = new Dictionary <string, object>() { { "typ", "JWT" }, { "cty", "JWT" }, { "keyid", "111-222-333" } }; privateX509Key = new X509Certificate2(Program.PrivateRsaX509Path, Program.PfxPassword, x509KSF); publicX509Key = new X509Certificate2(Program.PublicRsaX509Path, "", x509KSF); #if NETCORE rsa = (RSA)privateX509Key.PrivateKey; #else // .net frameworkでは、何故かコレが必要。 rsa = (RSA)AsymmetricAlgorithmCmnFunc.CreateSameKeySizeSP(privateX509Key.PrivateKey); #endif token = ""; token = JWT.Encode(payload, rsa, JwsAlgorithm.RS256, extraHeaders: headers); Program.VerifyResult("Adding extra headers to RS256", token, rsa); #endregion #region Strict validation // https://github.com/dvsekhvalnov/jose-jwt#strict-validation // 厳密な検証では、Algorithmを指定可能 MyDebug.OutputDebugAndConsole("Strict validation(RS256)", JWT.Decode(token, rsa, JwsAlgorithm.RS256)); #endregion #region Two-phase validation // https://github.com/dvsekhvalnov/jose-jwt#two-phase-validation // ヘッダのkeyidクレームからキーを取り出して復号化する方法。 //headers = JWT.Headers(token); // ・・・ //string hoge = JWT.Decode(token, "key"); #endregion #region Working with binary payload // https://github.com/dvsekhvalnov/jose-jwt#working-with-binary-payload #endregion #endregion #region Settings // https://github.com/dvsekhvalnov/jose-jwt#settings // グローバル設定 #region Example of JWTSettings // https://github.com/dvsekhvalnov/jose-jwt#example-of-jwtsettings #endregion #region Customizing json <-> object parsing & mapping // https://github.com/dvsekhvalnov/jose-jwt#customizing-json---object-parsing--mapping // マッピング // https://github.com/dvsekhvalnov/jose-jwt#example-of-newtonsoftjson-mapper // https://github.com/dvsekhvalnov/jose-jwt#example-of-servicestack-mapper #endregion #region Customizing algorithm implementations // https://github.com/dvsekhvalnov/jose-jwt#customizing-algorithm-implementations // https://github.com/dvsekhvalnov/jose-jwt#example-of-custom-algorithm-implementation #endregion #region Providing aliases // https://github.com/dvsekhvalnov/jose-jwt#providing-aliases #endregion #endregion #region Dealing with keys // https://github.com/dvsekhvalnov/jose-jwt#dealing-with-keys // https://github.com/dvsekhvalnov/jose-jwt#rsacryptoserviceprovider // - http://stackoverflow.com/questions/7444586/how-can-i-sign-a-file-using-rsa-and-sha256-with-net // - http://hintdesk.com/c-how-to-fix-invalid-algorithm-specified-when-signing-with-sha256/ // https://github.com/dvsekhvalnov/jose-jwt#if-you-have-only-rsa-private-key // - http://www.donaldsbaconbytes.com/2016/08/create-jwt-with-a-private-rsa-key/ #endregion #region Strong-Named assembly // https://github.com/dvsekhvalnov/jose-jwt#strong-named-assembly // - https://github.com/dvsekhvalnov/jose-jwt/issues/5 // - https://github.com/brutaldev/StrongNameSigner #endregion #region More examples // https://github.com/dvsekhvalnov/jose-jwt#more-examples // https://github.com/dvsekhvalnov/jose-jwt/blob/master/UnitTests/TestSuite.cs #endregion #endregion }
public static void hogehoge(string[] args) { try { #region Variables #region Env // https://github.com/dotnet/corefx/issues/29404#issuecomment-385287947 // *.pfxから証明書を開く場合、X509KeyStorageFlags.Exportableの指定が必要な場合がある。 // Linuxのキーは常にエクスポート可能だが、WindowsやMacOSでは必ずしもそうではない。 X509KeyStorageFlags x509KSF = 0; x509KSF = X509KeyStorageFlags.DefaultKeySet; #endregion #region Token string token = ""; IDictionary <string, object> headers = null; IDictionary <string, object> payload = null; payload = new Dictionary <string, object>() { { "sub", "*****@*****.**" }, { "exp", 1300819380 } }; #endregion #region Keys string jwk = ""; byte[] secretKey = null; byte[] x = null; byte[] y = null; byte[] d = null; string privateX509Path = ""; string publicX509Path = ""; X509Certificate2 publicX509Key = null; X509Certificate2 privateX509Key = null; RSA rsa = null; //DSA dsa = null; CngKey publicKeyOfCng = null; //CngKey privateKeyOfCng = null; ECParameters eCParameters = new ECParameters(); #endregion #region DigitalSign byte[] data = CustomEncode.StringToByte("hogehoge", CustomEncode.UTF_8); byte[] sign = null; #endregion #endregion #region Test of the X.509 Certificates #region RSA privateX509Path = @"SHA256RSA.pfx"; publicX509Path = @"SHA256RSA.cer"; privateX509Key = new X509Certificate2(privateX509Path, "test", x509KSF); publicX509Key = new X509Certificate2(publicX509Path, "", x509KSF); WriteLine.InspectPrivateX509Key("RSA", privateX509Key); WriteLine.InspectPublicX509Key("RSA", publicX509Key); #endregion #region DSA // https://github.com/dotnet/corefx/issues/18733#issuecomment-296723615 privateX509Path = @"SHA256DSA.pfx"; publicX509Path = @"SHA256DSA.cer"; privateX509Key = new X509Certificate2(privateX509Path, "test"); publicX509Key = new X509Certificate2(publicX509Path, ""); WriteLine.InspectPrivateX509Key("DSA", privateX509Key); WriteLine.InspectPublicX509Key("DSA", publicX509Key); DSA privateDSA = privateX509Key.GetDSAPrivateKey(); WriteLine.OutPutDebugAndConsole("privateDSA", (privateDSA == null ? "is null" : "is not null")); //DSA publicDSA = null; // publicX509Key.GetDSAPublicKey(); // Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException #endregion #region ECDsa // https://github.com/dotnet/corefx/issues/18733#issuecomment-296723615 privateX509Path = @"SHA256ECDSA.pfx"; publicX509Path = @"SHA256ECDSA.cer"; privateX509Key = new X509Certificate2(privateX509Path, "test"); publicX509Key = new X509Certificate2(publicX509Path, ""); WriteLine.InspectPrivateX509Key("ECDsa", privateX509Key); WriteLine.InspectPublicX509Key("ECDsa", publicX509Key); ECDsa privateECDsa = privateX509Key.GetECDsaPrivateKey(); WriteLine.OutPutDebugAndConsole("privateECDsa", (privateECDsa == null ? "is null" : "is not null")); ECDsa publicECDsa = publicX509Key.GetECDsaPublicKey(); WriteLine.OutPutDebugAndConsole("publicECDsa", (publicECDsa == null ? "is null" : "is not null")); #endregion #endregion WriteLine.OutPutDebugAndConsole("----------------------------------------------------------------------------------------------------"); #region Test of the OpenTouryo.Public.Security. DigitalSignParam dsParam = null; DigitalSignXML dsXML = null; DigitalSignX509 dsX509 = null; #region RSA dsParam = new DigitalSignParam(EnumDigitalSignAlgorithm.RsaOpenSsl_SHA256); sign = dsParam.Sign(data); WriteLine.OutPutDebugAndConsole("DigitalSignParam.Verify(RS256)", dsParam.Verify(data, sign).ToString()); dsXML = new DigitalSignXML(EnumDigitalSignAlgorithm.RsaOpenSsl_SHA256); sign = dsXML.Sign(data); WriteLine.OutPutDebugAndConsole("DigitalSignXML.Verify(RS256)", dsXML.Verify(data, sign).ToString()); dsX509 = new DigitalSignX509(@"SHA256RSA.pfx", "test", "SHA256"); sign = dsX509.Sign(data); WriteLine.OutPutDebugAndConsole("DigitalSignX509.Verify(RSA)", dsX509.Verify(data, sign).ToString()); // 鍵の相互変換 jwk = RsaPublicKeyConverter.ParamToJwk( ((RSA)dsX509.AsymmetricAlgorithm).ExportParameters(false)); WriteLine.OutPutDebugAndConsole("RSA JWK", jwk); dsParam = new DigitalSignParam( RsaPublicKeyConverter.JwkToParam(jwk), EnumDigitalSignAlgorithm.RsaCSP_SHA256); WriteLine.OutPutDebugAndConsole("DigitalSignX509.Verify(RSA JWK)", dsParam.Verify(data, sign).ToString()); #endregion #region DSA dsParam = new DigitalSignParam(EnumDigitalSignAlgorithm.DsaOpenSsl_SHA1); sign = dsParam.Sign(data); WriteLine.OutPutDebugAndConsole( "DigitalSignParam.Verify(DS1)", dsParam.Verify(data, sign).ToString()); dsXML = new DigitalSignXML(EnumDigitalSignAlgorithm.DsaOpenSsl_SHA1); sign = dsXML.Sign(data); WriteLine.OutPutDebugAndConsole( "DigitalSignXML.Verify(DS1)", dsXML.Verify(data, sign).ToString()); dsX509 = new DigitalSignX509(@"SHA256DSA.pfx", "test", "SHA256"); sign = dsX509.Sign(data); WriteLine.OutPutDebugAndConsole( "DigitalSignX509.Verify(DSA)", dsX509.Verify(data, sign).ToString()); #endregion #region ECDSA // .NET Core on Linux DigitalSignECDsaX509 ecDsX509 = new DigitalSignECDsaX509( @"SHA256ECDSA.pfx", "test", HashAlgorithmName.SHA256); sign = ecDsX509.Sign(data); WriteLine.OutPutDebugAndConsole( "DigitalSignX509.Verify(ECDSA)", ecDsX509.Verify(data, sign).ToString()); token = ""; token = JWT.Encode(payload, ((ECDsa)ecDsX509.AsymmetricAlgorithm), JwsAlgorithm.ES256); // 鍵の相互変換 jwk = EccPublicKeyConverter.ParamToJwk( ((ECDsa)ecDsX509.AsymmetricAlgorithm).ExportParameters(false)); WriteLine.OutPutDebugAndConsole("ECDSA JWK", jwk); DigitalSignECDsaOpenSsl ecDsParam = new DigitalSignECDsaOpenSsl( EccPublicKeyConverter.JwkToParam(jwk), HashAlgorithmCmnFunc.GetHashAlgorithmFromNameString(HashNameConst.SHA256)); WriteLine.OutPutDebugAndConsole( "DigitalSignX509.Verify(ECDSA JWK)", ecDsParam.Verify(data, sign).ToString()); Program.VerifyResult("JwsAlgorithm.ES256", token, ecDsParam.AsymmetricAlgorithm); #endregion #endregion WriteLine.OutPutDebugAndConsole("----------------------------------------------------------------------------------------------------"); #region Test of the jose-jwt #region JWT #region Unsecured JWT // Creating Plaintext (unprotected) Tokens // https://github.com/dvsekhvalnov/jose-jwt#creating-plaintext-unprotected-tokens token = ""; token = JWT.Encode(payload, null, JwsAlgorithm.none); WriteLine.OutPutDebugAndConsole("JwsAlgorithm.none", token); #endregion #region JWS (Creating signed Tokens) // https://github.com/dvsekhvalnov/jose-jwt#creating-signed-tokens #region HS-* family // HS256, HS384, HS512 // https://github.com/dvsekhvalnov/jose-jwt#hs--family secretKey = new byte[] { 164, 60, 194, 0, 161, 189, 41, 38, 130, 89, 141, 164, 45, 170, 159, 209, 69, 137, 243, 216, 191, 131, 47, 250, 32, 107, 231, 117, 37, 158, 225, 234 }; token = ""; token = JWT.Encode(payload, secretKey, JwsAlgorithm.HS256); Program.VerifyResult("JwsAlgorithm.HS256", token, secretKey); #endregion #region RS-* and PS-* family // RS256, RS384, RS512 and PS256, PS384, PS512 // https://github.com/dvsekhvalnov/jose-jwt#rs--and-ps--family // X509Certificate2 x509Certificate2 = new X509Certificate2(); privateX509Path = @"SHA256RSA.pfx"; publicX509Path = @"SHA256RSA.cer"; privateX509Key = new X509Certificate2(privateX509Path, "test", x509KSF); publicX509Key = new X509Certificate2(publicX509Path, "", x509KSF); token = ""; rsa = (RSA)privateX509Key.PrivateKey; token = JWT.Encode(payload, rsa, JwsAlgorithm.RS256); Program.VerifyResult("JwsAlgorithm.RS256", token, rsa); #endregion #region ES- * family // ES256, ES384, ES512 ECDSA signatures // https://github.com/dvsekhvalnov/jose-jwt#es---family x = new byte[] { 4, 114, 29, 223, 58, 3, 191, 170, 67, 128, 229, 33, 242, 178, 157, 150, 133, 25, 209, 139, 166, 69, 55, 26, 84, 48, 169, 165, 67, 232, 98, 9 }; y = new byte[] { 131, 116, 8, 14, 22, 150, 18, 75, 24, 181, 159, 78, 90, 51, 71, 159, 214, 186, 250, 47, 207, 246, 142, 127, 54, 183, 72, 72, 253, 21, 88, 53 }; d = new byte[] { 42, 148, 231, 48, 225, 196, 166, 201, 23, 190, 229, 199, 20, 39, 226, 70, 209, 148, 29, 70, 125, 14, 174, 66, 9, 198, 80, 251, 95, 107, 98, 206 }; eCParameters = new ECParameters(); // Curve eCParameters.Curve = EccPublicKeyConverter.GetECCurveFromCrvString( EccPublicKeyConverter.GetCrvStringFromXCoordinate(x)); // x, y, d eCParameters.Q.X = x; eCParameters.Q.Y = y; eCParameters.D = d; ECDsaOpenSsl eCDsaOpenSsl = new ECDsaOpenSsl(eCParameters.Curve); eCDsaOpenSsl.ImportParameters(eCParameters); token = ""; token = JWT.Encode(payload, eCDsaOpenSsl, JwsAlgorithm.ES256); Program.VerifyResult("JwsAlgorithm.ES256", token, eCDsaOpenSsl); try { privateX509Path = @"SHA256ECDSA.pfx"; publicX509Path = @"SHA256ECDSA.cer"; privateX509Key = new X509Certificate2(privateX509Path, "test"); publicX509Key = new X509Certificate2(publicX509Path, ""); // ECCurveを分析してみる。 ECCurve eCCurve = ((ECDsaOpenSsl)privateX509Key.GetECDsaPrivateKey()).ExportExplicitParameters(true).Curve; WriteLine.OutPutDebugAndConsole("Inspect ECCurve", ObjectInspector.Inspect(eCCurve)); token = ""; token = JWT.Encode(payload, privateX509Key.GetECDsaPrivateKey(), JwsAlgorithm.ES256); Program.VerifyResult("JwsAlgorithm.ES256", token, publicX509Key.GetECDsaPublicKey()); } catch (Exception ex) { WriteLine.OutPutDebugAndConsole("JwsAlgorithm.ES256", ex.GetType().ToString() + ", " + ex.Message); } #endregion #endregion #region JWE (Creating encrypted Tokens) // https://github.com/dvsekhvalnov/jose-jwt#creating-encrypted-tokens #region RSA-* key management family of algorithms // RSA-OAEP-256, RSA-OAEP and RSA1_5 key // https://github.com/dvsekhvalnov/jose-jwt#rsa--key-management-family-of-algorithms privateX509Path = @"SHA256RSA.pfx"; publicX509Path = @"SHA256RSA.cer"; privateX509Key = new X509Certificate2(privateX509Path, "test", x509KSF); publicX509Key = new X509Certificate2(publicX509Path, "", x509KSF); // RSAES-PKCS1-v1_5 and AES_128_CBC_HMAC_SHA_256 token = ""; token = JWT.Encode(payload, publicX509Key.PublicKey.Key, JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256); Program.VerifyResult("JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256", token, privateX509Key.PrivateKey); // RSAES-OAEP and AES GCM try { token = ""; token = JWT.Encode(payload, publicX509Key.PublicKey.Key, JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM); Program.VerifyResult("JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM", token, privateX509Key.PrivateKey); } catch (Exception ex) { // Unhandled Exception: System.DllNotFoundException: Unable to load DLL 'bcrypt.dll' at ubunntu WriteLine.OutPutDebugAndConsole("JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM", ex.GetType().ToString() + ", " + ex.Message); } #endregion #region Other key management family of algorithms secretKey = new byte[] { 164, 60, 194, 0, 161, 189, 41, 38, 130, 89, 141, 164, 45, 170, 159, 209, 69, 137, 243, 216, 191, 131, 47, 250, 32, 107, 231, 117, 37, 158, 225, 234 }; #region DIR direct pre-shared symmetric key family of algorithms // https://github.com/dvsekhvalnov/jose-jwt#dir-direct-pre-shared-symmetric-key-family-of-algorithms token = ""; token = JWT.Encode(payload, secretKey, JweAlgorithm.DIR, JweEncryption.A128CBC_HS256); Program.VerifyResult("JweAlgorithm.DIR, JweEncryption.A128CBC_HS256", token, secretKey); #endregion #region AES Key Wrap key management family of algorithms // AES128KW, AES192KW and AES256KW key management // https://github.com/dvsekhvalnov/jose-jwt#aes-key-wrap-key-management-family-of-algorithms token = ""; token = JWT.Encode(payload, secretKey, JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512); Program.VerifyResult("JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512", token, secretKey); #endregion #region AES GCM Key Wrap key management family of algorithms // AES128GCMKW, AES192GCMKW and AES256GCMKW key management // https://github.com/dvsekhvalnov/jose-jwt#aes-gcm-key-wrap-key-management-family-of-algorithms try { token = ""; token = JWT.Encode(payload, secretKey, JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512); Program.VerifyResult("JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512", token, secretKey); } catch (Exception ex) { // Unhandled Exception: System.DllNotFoundException: Unable to load DLL 'bcrypt.dll' at ubunntu WriteLine.OutPutDebugAndConsole("JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512", ex.GetType().ToString() + ", " + ex.Message); } #endregion #region ECDH-ES and ECDH-ES with AES Key Wrap key management family of algorithms // ECDH-ES and ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW key management // https://github.com/dvsekhvalnov/jose-jwt#ecdh-es-and-ecdh-es-with-aes-key-wrap-key-management-family-of-algorithms try { x = new byte[] { 4, 114, 29, 223, 58, 3, 191, 170, 67, 128, 229, 33, 242, 178, 157, 150, 133, 25, 209, 139, 166, 69, 55, 26, 84, 48, 169, 165, 67, 232, 98, 9 }; y = new byte[] { 131, 116, 8, 14, 22, 150, 18, 75, 24, 181, 159, 78, 90, 51, 71, 159, 214, 186, 250, 47, 207, 246, 142, 127, 54, 183, 72, 72, 253, 21, 88, 53 }; publicKeyOfCng = EccKey.New(x, y, usage: CngKeyUsages.KeyAgreement); token = ""; token = JWT.Encode(payload, publicKeyOfCng, JweAlgorithm.ECDH_ES, JweEncryption.A256GCM); Program.VerifyResult("JweAlgorithm.ECDH_ES, JweEncryption.A256GCM", token, publicKeyOfCng); } catch (Exception ex) { // System.NotImplementedException: 'not yet' WriteLine.OutPutDebugAndConsole("JweAlgorithm.ECDH_ES, JweEncryption.A256GCM", ex.GetType().ToString() + ", " + ex.Message); } #endregion #region PBES2 using HMAC SHA with AES Key Wrap key management family of algorithms token = ""; token = JWT.Encode(payload, "top secret", JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512); Program.VerifyResult("JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512", token, "top secret"); #endregion #endregion #endregion #endregion #endregion } catch (Exception ex) { WriteLine.OutPutDebugAndConsole(ex.ToString()); } }
static void Main(string[] args) { #region Variables OperatingSystem os = Environment.OSVersion; X509KeyStorageFlags x509KS = X509KeyStorageFlags.DefaultKeySet; string token = ""; IDictionary <string, object> headers = null; IDictionary <string, object> payload = null; payload = new Dictionary <string, object>() { { "sub", "*****@*****.**" }, { "exp", 1300819380 } }; #region Keys byte[] secretKey = null; byte[] x = null; byte[] y = null; byte[] d = null; string privateX509Path = ""; string publicX509Path = ""; X509Certificate2 publicX509Key = null; X509Certificate2 privateX509Key = null; CngKey publicKeyOfCng = null; CngKey privateKeyOfCng = null; #endregion #endregion #region Certificates #region RSA privateX509Path = @"SHA256RSA.pfx"; publicX509Path = @"SHA256RSA.cer"; privateX509Key = new X509Certificate2(privateX509Path, "test", x509KS); publicX509Key = new X509Certificate2(publicX509Path, "", x509KS); Program.PrivateX509KeyInspector("RSA", privateX509Key); Program.PublicX509KeyInspector("RSA", publicX509Key); #endregion #region DSA // https://github.com/dotnet/corefx/issues/18733#issuecomment-296723615 privateX509Path = @"SHA256DSA.pfx"; publicX509Path = @"SHA256DSA.cer"; privateX509Key = new X509Certificate2(privateX509Path, "test"); publicX509Key = new X509Certificate2(publicX509Path, ""); Program.PrivateX509KeyInspector("DSA", privateX509Key); Program.PublicX509KeyInspector("DSA", publicX509Key); DSA privateDSA = privateX509Key.GetDSAPrivateKey(); Program.MyWriteLine("privateDSA: " + (privateDSA == null ? "is null" : "is not null")); DSA publicDSA = null; // publicX509Key.GetDSAPublicKey(); // Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException #endregion #region ECDsa // https://github.com/dotnet/corefx/issues/18733#issuecomment-296723615 privateX509Path = @"SHA256ECDSA.pfx"; publicX509Path = @"SHA256ECDSA.cer"; privateX509Key = new X509Certificate2(privateX509Path, "test"); publicX509Key = new X509Certificate2(publicX509Path, ""); Program.PrivateX509KeyInspector("ECDsa", privateX509Key); Program.PublicX509KeyInspector("ECDsa", publicX509Key); ECDsa privateECDsa = privateX509Key.GetECDsaPrivateKey(); Program.MyWriteLine("privateECDsa: " + (privateECDsa == null ? "is null" : "is not null")); ECDsa publicECDsa = publicX509Key.GetECDsaPublicKey(); Program.MyWriteLine("publicECDsa: " + (publicECDsa == null ? "is null" : "is not null")); #endregion #endregion Program.MyWriteLine("----------------------------------------------------------------------------------------------------"); #region JWT #region Unsecured JWT // Creating Plaintext (unprotected) Tokens // https://github.com/dvsekhvalnov/jose-jwt#creating-plaintext-unprotected-tokens token = ""; token = JWT.Encode(payload, null, JwsAlgorithm.none); Program.MyWriteLine("JwsAlgorithm.none: " + token); #endregion #region JWS (Creating signed Tokens) // https://github.com/dvsekhvalnov/jose-jwt#creating-signed-tokens #region HS-* family // HS256, HS384, HS512 // https://github.com/dvsekhvalnov/jose-jwt#hs--family secretKey = new byte[] { 164, 60, 194, 0, 161, 189, 41, 38, 130, 89, 141, 164, 45, 170, 159, 209, 69, 137, 243, 216, 191, 131, 47, 250, 32, 107, 231, 117, 37, 158, 225, 234 }; token = ""; token = JWT.Encode(payload, secretKey, JwsAlgorithm.HS256); Program.VerifyResult("JwsAlgorithm.HS256: ", token, secretKey); #endregion #region RS-* and PS-* family // RS256, RS384, RS512 and PS256, PS384, PS512 // https://github.com/dvsekhvalnov/jose-jwt#rs--and-ps--family // X509Certificate2 x509Certificate2 = new X509Certificate2(); privateX509Path = @"SHA256RSA.pfx"; publicX509Path = @"SHA256RSA.cer"; privateX509Key = new X509Certificate2(privateX509Path, "test", x509KS); publicX509Key = new X509Certificate2(publicX509Path, "", x509KS); token = ""; token = JWT.Encode(payload, privateX509Key.PrivateKey, JwsAlgorithm.RS256); Program.VerifyResult("JwsAlgorithm.RS256: ", token, publicX509Key.PublicKey.Key); #endregion #region ES- * family // ES256, ES384, ES512 ECDSA signatures // https://github.com/dvsekhvalnov/jose-jwt#es---family x = new byte[] { 4, 114, 29, 223, 58, 3, 191, 170, 67, 128, 229, 33, 242, 178, 157, 150, 133, 25, 209, 139, 166, 69, 55, 26, 84, 48, 169, 165, 67, 232, 98, 9 }; y = new byte[] { 131, 116, 8, 14, 22, 150, 18, 75, 24, 181, 159, 78, 90, 51, 71, 159, 214, 186, 250, 47, 207, 246, 142, 127, 54, 183, 72, 72, 253, 21, 88, 53 }; d = new byte[] { 42, 148, 231, 48, 225, 196, 166, 201, 23, 190, 229, 199, 20, 39, 226, 70, 209, 148, 29, 70, 125, 14, 174, 66, 9, 198, 80, 251, 95, 107, 98, 206 }; if (os.Platform == PlatformID.Win32NT) { // https://github.com/dvsekhvalnov/jose-jwt/blob/master/jose-jwt/Security/Cryptography/EccKey.cs privateKeyOfCng = EccKey.New(x, y, d); publicKeyOfCng = EccKey.New(x, y); token = ""; token = JWT.Encode(payload, privateKeyOfCng, JwsAlgorithm.ES256); Program.VerifyResult("JwsAlgorithm.ES256: ", token, publicKeyOfCng); } else // == PlatformID.Unix { // (x, y, d)を使用して、ECCurveからECDsaOpenSslを生成できれば...。 //ECCurve eCCurve = new ECCurve(); ////eCCurve.A = x; ////eCCurve.B = y; ////ECDsaOpenSsl ecd = new ECDsaOpenSsl(eCCurve); ////eCCurve = ecd.ExportExplicitParameters(true).Curve; //token = ""; //token = JWT.Encode(payload, new ECDsaOpenSsl(eCCurve), JwsAlgorithm.ES256); //Program.VerifyResult("JwsAlgorithm.ES256: ", token, new ECDsaOpenSsl(eCCurve)); } privateX509Path = @"SHA256ECDSA.pfx"; publicX509Path = @"SHA256ECDSA.cer"; privateX509Key = new X509Certificate2(privateX509Path, "test"); publicX509Key = new X509Certificate2(publicX509Path, ""); try { if (os.Platform == PlatformID.Unix) { // ECCurveを分析してみる。 ECCurve eCCurve = ((ECDsaOpenSsl)privateX509Key.GetECDsaPrivateKey()).ExportExplicitParameters(true).Curve; Program.MyWriteLine("Inspect ECCurve: " + ObjectInspector.Inspect(eCCurve)); } token = ""; token = JWT.Encode(payload, privateX509Key.GetECDsaPrivateKey(), JwsAlgorithm.ES256); Program.VerifyResult("JwsAlgorithm.ES256: ", token, publicX509Key.GetECDsaPublicKey()); } catch (Exception ex) { Program.MyWriteLine("JwsAlgorithm.ES256: " + ex.GetType().ToString() + ", " + ex.Message); } #endregion #endregion #region JWE (Creating encrypted Tokens) // https://github.com/dvsekhvalnov/jose-jwt#creating-encrypted-tokens #region RSA-* key management family of algorithms // RSA-OAEP-256, RSA-OAEP and RSA1_5 key // https://github.com/dvsekhvalnov/jose-jwt#rsa--key-management-family-of-algorithms privateX509Path = @"SHA256RSA.pfx"; publicX509Path = @"SHA256RSA.cer"; privateX509Key = new X509Certificate2(privateX509Path, "test", x509KS); publicX509Key = new X509Certificate2(publicX509Path, "", x509KS); // RSAES-PKCS1-v1_5 and AES_128_CBC_HMAC_SHA_256 token = ""; token = JWT.Encode(payload, publicX509Key.PublicKey.Key, JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256); Program.VerifyResult("JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256: ", token, privateX509Key.PrivateKey); // RSAES-OAEP and AES GCM try { token = ""; token = JWT.Encode(payload, publicX509Key.PublicKey.Key, JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM); Program.VerifyResult("JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM: ", token, privateX509Key.PrivateKey); } catch (Exception ex) { // Unhandled Exception: System.DllNotFoundException: Unable to load DLL 'bcrypt.dll' at ubunntu Program.MyWriteLine("JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM: " + ex.GetType().ToString() + ", " + ex.Message); } #endregion #region Other key management family of algorithms secretKey = new byte[] { 164, 60, 194, 0, 161, 189, 41, 38, 130, 89, 141, 164, 45, 170, 159, 209, 69, 137, 243, 216, 191, 131, 47, 250, 32, 107, 231, 117, 37, 158, 225, 234 }; #region DIR direct pre-shared symmetric key family of algorithms // https://github.com/dvsekhvalnov/jose-jwt#dir-direct-pre-shared-symmetric-key-family-of-algorithms token = ""; token = JWT.Encode(payload, secretKey, JweAlgorithm.DIR, JweEncryption.A128CBC_HS256); Program.VerifyResult("JweAlgorithm.DIR, JweEncryption.A128CBC_HS256: ", token, secretKey); #endregion #region AES Key Wrap key management family of algorithms // AES128KW, AES192KW and AES256KW key management // https://github.com/dvsekhvalnov/jose-jwt#aes-key-wrap-key-management-family-of-algorithms token = ""; token = JWT.Encode(payload, secretKey, JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512); Program.VerifyResult("JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512: ", token, secretKey); #endregion #region AES GCM Key Wrap key management family of algorithms // AES128GCMKW, AES192GCMKW and AES256GCMKW key management // https://github.com/dvsekhvalnov/jose-jwt#aes-gcm-key-wrap-key-management-family-of-algorithms try { token = ""; token = JWT.Encode(payload, secretKey, JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512); Program.VerifyResult("JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512: ", token, secretKey); } catch (Exception ex) { // Unhandled Exception: System.DllNotFoundException: Unable to load DLL 'bcrypt.dll' at ubunntu Program.MyWriteLine("JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512: " + ex.GetType().ToString() + ", " + ex.Message); } #endregion #region ECDH-ES and ECDH-ES with AES Key Wrap key management family of algorithms // ECDH-ES and ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW key management // https://github.com/dvsekhvalnov/jose-jwt#ecdh-es-and-ecdh-es-with-aes-key-wrap-key-management-family-of-algorithms try { x = new byte[] { 4, 114, 29, 223, 58, 3, 191, 170, 67, 128, 229, 33, 242, 178, 157, 150, 133, 25, 209, 139, 166, 69, 55, 26, 84, 48, 169, 165, 67, 232, 98, 9 }; y = new byte[] { 131, 116, 8, 14, 22, 150, 18, 75, 24, 181, 159, 78, 90, 51, 71, 159, 214, 186, 250, 47, 207, 246, 142, 127, 54, 183, 72, 72, 253, 21, 88, 53 }; publicKeyOfCng = EccKey.New(x, y, usage: CngKeyUsages.KeyAgreement); token = ""; token = JWT.Encode(payload, publicKeyOfCng, JweAlgorithm.ECDH_ES, JweEncryption.A256GCM); Program.VerifyResult("JweAlgorithm.ECDH_ES, JweEncryption.A256GCM: ", token, publicKeyOfCng); } catch (Exception ex) { // System.NotImplementedException: 'not yet' Program.MyWriteLine("JweAlgorithm.ECDH_ES, JweEncryption.A256GCM: " + ex.GetType().ToString() + ", " + ex.Message); } #endregion #region PBES2 using HMAC SHA with AES Key Wrap key management family of algorithms token = ""; token = JWT.Encode(payload, "top secret", JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512); Program.VerifyResult("JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512: ", token, "top secret"); #endregion #endregion #endregion #endregion Program.MyWriteLine("----------------------------------------------------------------------------------------------------"); #region ELSE #region Additional utilities // https://github.com/dvsekhvalnov/jose-jwt#additional-utilities #region Adding extra headers // https://github.com/dvsekhvalnov/jose-jwt#adding-extra-headers headers = new Dictionary <string, object>() { { "typ", "JWT" }, { "cty", "JWT" }, { "keyid", "111-222-333" } }; privateX509Path = @"SHA256RSA.pfx"; publicX509Path = @"SHA256RSA.cer"; privateX509Key = new X509Certificate2(privateX509Path, "test", x509KS); publicX509Key = new X509Certificate2(publicX509Path, "", x509KS); token = ""; token = JWT.Encode(payload, privateX509Key.PrivateKey, JwsAlgorithm.RS256, extraHeaders: headers); Program.VerifyResult("Adding extra headers to RS256: ", token, privateX509Key.PrivateKey); #endregion #region Strict validation // https://github.com/dvsekhvalnov/jose-jwt#strict-validation // 厳密な検証では、Algorithmを指定可能 Program.MyWriteLine("Strict validation(RS256): " + JWT.Decode(token, privateX509Key.PrivateKey, JwsAlgorithm.RS256)); #endregion #region Two-phase validation // https://github.com/dvsekhvalnov/jose-jwt#two-phase-validation // ヘッダのkeyidクレームからキーを取り出して復号化する方法。 //headers = JWT.Headers(token); // ・・・ //string hoge = JWT.Decode(token, "key"); #endregion #region Working with binary payload // https://github.com/dvsekhvalnov/jose-jwt#working-with-binary-payload #endregion #endregion #region Settings // https://github.com/dvsekhvalnov/jose-jwt#settings // グローバル設定 #region Example of JWTSettings // https://github.com/dvsekhvalnov/jose-jwt#example-of-jwtsettings #endregion #region Customizing json <-> object parsing & mapping // https://github.com/dvsekhvalnov/jose-jwt#customizing-json---object-parsing--mapping // マッピング // https://github.com/dvsekhvalnov/jose-jwt#example-of-newtonsoftjson-mapper // https://github.com/dvsekhvalnov/jose-jwt#example-of-servicestack-mapper #endregion #region Customizing algorithm implementations // https://github.com/dvsekhvalnov/jose-jwt#customizing-algorithm-implementations // https://github.com/dvsekhvalnov/jose-jwt#example-of-custom-algorithm-implementation #endregion #region Providing aliases // https://github.com/dvsekhvalnov/jose-jwt#providing-aliases #endregion #endregion #region Dealing with keys // https://github.com/dvsekhvalnov/jose-jwt#dealing-with-keys // https://github.com/dvsekhvalnov/jose-jwt#rsacryptoserviceprovider // - http://stackoverflow.com/questions/7444586/how-can-i-sign-a-file-using-rsa-and-sha256-with-net // - http://hintdesk.com/c-how-to-fix-invalid-algorithm-specified-when-signing-with-sha256/ // https://github.com/dvsekhvalnov/jose-jwt#if-you-have-only-rsa-private-key // - http://www.donaldsbaconbytes.com/2016/08/create-jwt-with-a-private-rsa-key/ #endregion #region Strong-Named assembly // https://github.com/dvsekhvalnov/jose-jwt#strong-named-assembly // - https://github.com/dvsekhvalnov/jose-jwt/issues/5 // - https://github.com/brutaldev/StrongNameSigner #endregion #region More examples // https://github.com/dvsekhvalnov/jose-jwt#more-examples // https://github.com/dvsekhvalnov/jose-jwt/blob/master/UnitTests/TestSuite.cs #endregion #endregion Console.ReadKey(); }
/// <summary> /// Encrypt Async /// </summary> /// <param name="value">The value to encrypt as JWE string</param> /// <returns>JWE string</returns> public async Task <string> EncryptAsync(string value) { JsonWebKey publicJsonWebKey = null; try { publicJsonWebKey = await this.keyResolver.GetEncryptionKeyAsync(); if (publicJsonWebKey == null) { throw new EncryptionException(string.Format("Encryption key not found by KeyResolver.")); } var encodedJwe = string.Empty; var extraHeaders = new Dictionary <string, object> { { "kid", publicJsonWebKey.Kid }, { "kty", publicJsonWebKey.Kty } }; if (publicJsonWebKey.Kty == "EC") { var xByteArray = Jose.Base64Url.Decode(publicJsonWebKey.X); var yByteArray = Jose.Base64Url.Decode(publicJsonWebKey.Y); var eccKey = EccKey.New(xByteArray, yByteArray, null, CngKeyUsages.KeyAgreement); encodedJwe = Jose.JWT.Encode(value, eccKey, Jose.JweAlgorithm.ECDH_ES_A256KW, Jose.JweEncryption.A256GCM, null, extraHeaders, null); } else if (publicJsonWebKey.Kty == "RSA") { var keyParams = new RSAParameters { Exponent = Jose.Base64Url.Decode(publicJsonWebKey.E), Modulus = Jose.Base64Url.Decode(publicJsonWebKey.N) }; var rsa = RSA.Create(); rsa.ImportParameters(keyParams); encodedJwe = Jose.JWT.Encode(value, rsa, Jose.JweAlgorithm.RSA_OAEP_256, Jose.JweEncryption.A256GCM, null, extraHeaders, null); } else { throw new EncryptionException("Unsupport Json Web Key type."); } logger.LogDebug("Encrypting data with keyid: {0}, type: {1}", publicJsonWebKey.Kid, publicJsonWebKey.Kty); return(Constants.CIPHER_HEADER + encodedJwe); } catch (Jose.EncryptionException iaEx) { if (publicJsonWebKey == null) { logger.LogError(iaEx, "An Encryption Exceptionn occurred."); } else { logger.LogError(iaEx, "An Encryption Exceptionn occurred. keyid: {0}, type: {1}", publicJsonWebKey.Kid, publicJsonWebKey.Kty); } throw new EncryptionException("Unable to decrypt data.", iaEx); } catch (Jose.InvalidAlgorithmException iaEx) { if (publicJsonWebKey == null) { logger.LogError(iaEx, "An Invalid Algorithm Exception occurred."); } else { logger.LogError(iaEx, "An Invalid Algorithm Exception occurred. keyid: {0}, type: {1}", publicJsonWebKey.Kid, publicJsonWebKey.Kty); } throw new EncryptionException("Unable to decrypt data.", iaEx); } catch (EncryptionException eeEx) { if (publicJsonWebKey == null) { logger.LogError(eeEx, "An Encryption Exception Occurred: Value: {0}", value); } else { logger.LogError(eeEx, "An Encryption Exception Occurred: Keyid: {0}, type: {1}", publicJsonWebKey.Kid, publicJsonWebKey.Kty); } throw; } catch (Exception ex) { if (ex.GetType() == typeof(NotImplementedException)) { throw; } else { logger.LogError(ex, "An Exception Occurred: Keyid: {0}, type: {1}", publicJsonWebKey.Kid, publicJsonWebKey.Kty); throw new EncryptionException("Unable to encrypt data.", ex); } } }
/// <summary> /// Decrypt Async /// </summary> /// <param name="cipher">Cipher string</param> /// <returns>Descrypted string</returns> public async Task <string> DecryptAsync(string cipher) { var privateJsonWebKey = default(JsonWebKey); try { if (string.IsNullOrEmpty(cipher) || !cipher.StartsWith(Constants.CIPHER_HEADER, StringComparison.Ordinal)) { throw new InvalidHeaderException("Invalid encryption header."); } var value = default(string); var requestedprivateJsonWebKey = default(JsonWebKey); try { cipher = cipher.Substring(Constants.CIPHER_HEADER.Length); var cipherArray = cipher.Split(new char[] { '.' }); var json = Encoding.UTF8.GetString(Jose.Base64Url.Decode(cipherArray[0])); requestedprivateJsonWebKey = new JsonWebKey(json); } catch (ArgumentNullException anEx) { throw new SerializerException("Unable to deserializer value.", anEx); } catch (ArgumentException aEx) { throw new SerializerException("Unable to deserializer value.", aEx); } privateJsonWebKey = await this.keyResolver.GetDecryptionKeyAsync(requestedprivateJsonWebKey.Kid); if (privateJsonWebKey == null) { throw new EncryptionException(string.Format("Decryption key not found. ID: '{0}'.", requestedprivateJsonWebKey.Kid)); } if (privateJsonWebKey.Kty == "EC") { var xByteArray = Jose.Base64Url.Decode(privateJsonWebKey.X); var yByteArray = Jose.Base64Url.Decode(privateJsonWebKey.Y); var dByteArray = Jose.Base64Url.Decode(privateJsonWebKey.D); var privateKey = EccKey.New(xByteArray, yByteArray, dByteArray, CngKeyUsages.KeyAgreement); value = Jose.JWT.Decode(cipher, privateKey); } else if (privateJsonWebKey.Kty == "RSA") { var keyParams = new RSAParameters { Exponent = Jose.Base64Url.Decode(privateJsonWebKey.E), Modulus = Jose.Base64Url.Decode(privateJsonWebKey.N), P = Jose.Base64Url.Decode(privateJsonWebKey.P), Q = Jose.Base64Url.Decode(privateJsonWebKey.Q), D = Jose.Base64Url.Decode(privateJsonWebKey.D), InverseQ = Jose.Base64Url.Decode(privateJsonWebKey.QI), DP = Jose.Base64Url.Decode(privateJsonWebKey.DQ), DQ = Jose.Base64Url.Decode(privateJsonWebKey.DP) }; var rsa = RSA.Create(); rsa.ImportParameters(keyParams); value = Jose.JWT.Decode(cipher, rsa, Jose.JweAlgorithm.RSA_OAEP_256, Jose.JweEncryption.A256GCM); } else { throw new EncryptionException("Unsupport Json Web Key type."); } logger.LogDebug("Decrypted data with keyid: {0}, type: {1}, value: {2}", privateJsonWebKey.Kid, privateJsonWebKey.Kty, value); return(value); } catch (Jose.EncryptionException iaEx) { if (privateJsonWebKey == null) { logger.LogError(iaEx, "An Encryption Exceptionn occurred."); } else { logger.LogError(iaEx, "An Encryption Exceptionn occurred. keyid: {0}, type: {1}", privateJsonWebKey.Kid, privateJsonWebKey.Kty); } throw new EncryptionException("Unable to decrypt data.", iaEx); } catch (Jose.InvalidAlgorithmException iaEx) { if (privateJsonWebKey == null) { logger.LogError(iaEx, "An Invalid Algorithm Exception occurred."); } else { logger.LogError(iaEx, "An Invalid Algorithm Exception occurred. keyid: {0}, type: {1}", privateJsonWebKey.Kid, privateJsonWebKey.Kty); } throw new EncryptionException("Unable to decrypt data.", iaEx); } catch (InvalidHeaderException ihEx) { if (privateJsonWebKey == null) { logger.LogError(ihEx, "An Invalid Header Exception occurred."); } else { logger.LogError(ihEx, "An Invalid Header Exception occurred. keyid: {0}, type: {1}", privateJsonWebKey.Kid, privateJsonWebKey.Kty); } throw; } catch (SerializerException sEx) { if (privateJsonWebKey == null) { logger.LogError(sEx.InnerException, "Unable to deserializer value."); } else { logger.LogError(sEx, "Unable to deserializer value.: Keyid: {0}, type: {1}", privateJsonWebKey.Kid, privateJsonWebKey.Kty); } throw; } catch (EncryptionException eEx) { if (privateJsonWebKey == null) { logger.LogError(eEx, "An Decryption Exception Occurred"); } else { logger.LogError(eEx, "An Decryption Exception Occurred: Keyid: {0}, type: {1}", privateJsonWebKey.Kid, privateJsonWebKey.Kty); } throw; } catch (Exception ex) { if (privateJsonWebKey == null) { logger.LogError(ex, "An Decryption Exception Occurred"); } else { logger.LogError(ex, "An Exception Occurred: Keyid: {0}, type: {1}", privateJsonWebKey.Kid, privateJsonWebKey.Kty); } throw new EncryptionException("Unable to decrypt data.", ex); } }