public Signer(JWK key, string algorithm = null) { if (algorithm != null) { AddAttribute("alg", algorithm, UNPROTECTED); } if (key.ContainsName("kid")) { AddAttribute("kid", key.AsString("kid"), UNPROTECTED); } if (key.ContainsName("use")) { string usage = key.AsString("use"); if (usage != "sig") { throw new JoseException("Key cannot be used for encrytion"); } } #if false if (key.ContainsName("key_ops")) { JSON usageObject = key ["key_ops"]; bool validUsage = false; if (usageObject.Type != CBORType.Array) { throw new Exception("key_ops is incorrectly formed"); } for (int i = 0; i < usageObject.Count; i++) { switch (usageObject[i].AsString()) { case "encrypt": case "keywrap": validUsage = true; break; } } string usage = key.AsString("key_ops"); if (!validUsage) { throw new Exception("Key cannot be used for encryption"); } } #endif keyToSign = key; }
static Com.AugustCellars.JOSE.Recipient GetRecipient(CBORObject control) { Com.AugustCellars.JOSE.JWK key; if (!control.ContainsKey("alg")) { throw new Exception("Recipient missing alg field"); } if (control.ContainsKey("key")) { key = new Com.AugustCellars.JOSE.JWK(control["key"]); } else if (control.ContainsKey("pwd")) { key = new Com.AugustCellars.JOSE.JWK(); key.Add("kty", "oct"); key.Add("k", Com.AugustCellars.JOSE.Message.base64urlencode(Encoding.UTF8.GetBytes(control["pwd"].AsString()))); } else { throw new Exception("No key defined for a recipient"); } Com.AugustCellars.JOSE.Recipient recipient = new Com.AugustCellars.JOSE.Recipient(key, control["alg"].AsString()); // Double check that alg is the same as in the attributes recipient.ClearProtected(); recipient.ClearUnprotected(); if (control.ContainsKey("protected")) { AddAttributes(recipient, control["protected"], 0); } if (control.ContainsKey("unprotected")) { AddAttributes(recipient, control["unprotected"], 1); } if (control.ContainsKey("sender_key")) { Com.AugustCellars.JOSE.JWK myKey = new Com.AugustCellars.JOSE.JWK(control["sender_key"]); recipient.SetSenderKey(myKey); } return(recipient); }
private byte[] AES_KeyUnwrap(JWK keyObject, int keySize, byte[] rgbKey = null) { if (keyObject != null) { if (keyObject.AsString("kty") != "oct") { return(null); } rgbKey = keyObject.AsBytes("k"); } if (rgbKey != null && rgbKey.Length != keySize / 8) { throw new JoseException("Key is not the correct size"); } AesWrapEngine foo = new AesWrapEngine(); KeyParameter parameters = new KeyParameter(rgbKey); foo.Init(false, parameters); _payload = foo.Unwrap(_rgbEncrypted, 0, _rgbEncrypted.Length); return(_payload); }
private byte[] ECDH_GenerateSecret(JWK key, EncryptMessage msg) { JWK epk; if ((key.AsString("kty") != "EC") && (key.AsString("kty") != "OKP")) { throw new JoseException("Not an EC or OKP Key"); } if (_mSenderKey != null) { epk = _mSenderKey; } else { CBORObject epkT = FindAttr("epk", msg); if (epkT == null) { throw new JoseException("No Ephemeral key"); } epk = new JWK(epkT); } if (epk.AsString("crv") != key.AsString("crv")) { throw new JoseException("not a match of curves"); } if (key.AsString("kty") == "EC") { // Get the curve X9ECParameters p = NistNamedCurves.GetByName(key.AsString("crv")); ECDomainParameters parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H); Org.BouncyCastle.Math.EC.ECPoint pubPoint = p.Curve.CreatePoint(epk.AsBigInteger("x"), epk.AsBigInteger("y")); ECPublicKeyParameters pub = new ECPublicKeyParameters(pubPoint, parameters); ECPrivateKeyParameters priv = new ECPrivateKeyParameters(key.AsBigInteger("d"), parameters); IBasicAgreement e1 = new ECDHBasicAgreement(); e1.Init(priv); BigInteger k1 = e1.CalculateAgreement(pub); return(k1.ToByteArrayUnsigned()); } else { switch (epk.AsString("crv")) { case "X25519": { X25519PublicKeyParameters pub = new X25519PublicKeyParameters(epk.AsBytes("x"), 0); X25519PrivateKeyParameters priv = new X25519PrivateKeyParameters(key.AsBytes("d"), 0); X25519Agreement agree = new X25519Agreement(); agree.Init(priv); byte[] secret = new byte[32]; agree.CalculateAgreement(pub, secret, 0); return(secret); } default: throw new JoseException("Unsupported curve"); } } }
public void SetSenderKey(JWK senderKey) { _mSenderKey = senderKey; }
public void SetKey(JWK newKey) { _mKey = newKey; }
public Recipient(JWK key, string algorithm = null, EncryptMessage msg = null) { if (algorithm == null && key.ContainsName("alg")) { algorithm = key.AsString("alg"); } if (algorithm != null) { switch (algorithm) { case "dir": // Direct encryption mode case "A128GCM": case "A192GCM": case "A256GCM": if (key.AsString("kty") != "oct") { throw new JoseException("Invalid parameters"); } RecipientType = RecipientType.Direct; algorithm = "dir"; break; case "ECDH-ES": #if DEBUG case "ECDH-SS": #endif // DEBUG if ((key.AsString("kty") != "EC") && (key.AsString("kty") != "OKP")) { throw new JoseException("Invalid Parameters"); } RecipientType = RecipientType.KeyAgreeDirect; break; case "RSA1_5": case "RSA-OAEP": case "RSA-OAEP-256": if (key.AsString("kty") != "RSA") { throw new JoseException("Invalid Parameter"); } RecipientType = RecipientType.KeyTransport; break; case "A128KW": case "A192KW": case "A256KW": case "A128GCMKW": case "A192GCMKW": case "A256GCMKW": if (key.AsString("kty") != "oct") { throw new JoseException("Invalid Parameter"); } RecipientType = RecipientType.KeyWrap; break; case "ECDH-ES+A128KW": case "ECDH-ES+A192KW": case "ECDH-ES+A256KW": if ((key.AsString("kty") != "EC") && (key.AsString("kty") != "OKP")) { throw new JoseException("Invalid Parameter"); } RecipientType = RecipientType.KeyAgree; break; case "PBES2-HS256+A128KW": case "PBES2-HS384+A192KW": case "PBES2-HS512+A256KW": if (key.AsString("kty") != "oct") { throw new JoseException("Invalid Parameter"); } RecipientType = RecipientType.Password; break; default: throw new JoseException("Unrecognized recipient algorithm"); } _mKey = key; if (FindAttr("alg", msg) == null) { AddAttribute("alg", algorithm, UNPROTECTED); } } else { switch (key.AsString("kty")) { case "oct": RecipientType = RecipientType.KeyWrap; switch (key.AsBytes("k").Length) { case 128 / 8: algorithm = "A128KW"; break; case 192 / 8: algorithm = "A192KW"; break; case 256 / 8: algorithm = "A256KW"; break; default: throw new JoseException("Key size does not match any algorthms"); } break; case "RSA": RecipientType = RecipientType.KeyTransport; algorithm = "RSA-OAEP-256"; break; case "EC": RecipientType = RecipientType.KeyAgree; algorithm = "ECDH-ES+A128KW"; break; } if (FindAttr("alg", msg) == null) { AddAttribute("alg", algorithm, UNPROTECTED); } _mKey = key; } if (key.ContainsName("use")) { string usage = key.AsString("use"); if (usage != "enc") { throw new JoseException("Key cannot be used for encrytion"); } } if (key.ContainsName("key_ops")) { string usageObject = key.AsString("key_ops"); bool validUsage = false; string[] usageArray = usageObject.Split(','); for (int i = 0; i < usageArray.Length; i++) { switch (usageArray[i]) { case "encrypt": case "keywrap": validUsage = true; break; } } if (!validUsage) { throw new JoseException("Key cannot be used for encryption"); } } if (key.ContainsName("kid") && (FindAttr("kid", msg) == null)) { AddAttribute("kid", key.AsString("kid"), UNPROTECTED); } }
public byte[] Decrypt(int cbitKey, EncryptMessage msg) { JWK key = _mKey; if (key == null) { throw new JoseException("No key specified."); } string alg; alg = FindAttr("alg", msg).AsString(); switch (alg) { case "dir": if (key.AsString("kty") != "oct") { return(null); } return(key.AsBytes("k")); case "ECDH-ES": { if ((key.AsString("kty") != "EC") && (key.AsString("kty") != "OKP")) { return(null); } byte[] secret = Ecdh(key, msg); byte[] kwKey = Kdf(secret, msg, cbitKey, FindAttr("enc", msg).AsString()); return(kwKey); } case "A128KW": case "A192KW": case "A256KW": if (key.AsString("kty") != "oct") { return(null); } return(AES_KeyWrap(key.AsBytes("k"))); case "A128GCMKW": case "A192GCMKW": case "A256GCMKW": if (key.AsString("kty") != "oct") { return(null); } return(AESGCM_KeyWrap(key.AsBytes("k"), msg)); case "PBES2-HS256+A128KW": case "PBES2-HS384+A192KW": case "PBES2-HS512+A256KW": { if (key.AsString("kty") != "oct") { return(null); } byte[] saltInput = Message.base64urldecode(FindAttr("p2s", msg).AsString()); byte[] algBytes = Encoding.UTF8.GetBytes(alg); byte[] salt = new byte[alg.Length + 1 + saltInput.Length]; Array.Copy(algBytes, salt, algBytes.Length); Array.Copy(saltInput, 0, salt, algBytes.Length + 1, saltInput.Length); int iterCount = FindAttr("p2c", msg).AsInt32(); byte[] rgbSecret = PBKDF2(key.AsBytes("k"), salt, iterCount, 256 / 8, new Sha512Digest()); return(AES_KeyWrap(rgbSecret)); } case "RSA-OAEP-256": case "RSA-OAEP": { IAsymmetricBlockCipher cipher = new OaepEncoding(new RsaEngine(), alg == "RSA-OAEP" ? (IDigest) new Sha1Digest() : new Sha256Digest()); RsaKeyParameters prv = new RsaPrivateCrtKeyParameters(key.AsBigInteger("n"), key.AsBigInteger("e"), key.AsBigInteger("d"), key.AsBigInteger("p"), key.AsBigInteger("q"), key.AsBigInteger("dp"), key.AsBigInteger("dq"), key.AsBigInteger("qi")); cipher.Init(false, prv); byte[] outBytes = cipher.ProcessBlock(_rgbEncrypted, 0, _rgbEncrypted.Length); return(outBytes); } case "ECDH-ES+A128KW": { if ((key.AsString("kty") != "EC") && (key.AsString("kty") != "OKP")) { return(null); } byte[] secret = Ecdh(key, msg); byte[] kwKey = Kdf(secret, msg, 128, FindAttr("alg", msg).AsString()); return(AES_KeyWrap(kwKey)); } case "ECDH-ES+A192KW": { if (key.AsString("kty") != "EC") { return(null); } byte[] secret = Ecdh(key, msg); byte[] kwKey = Kdf(secret, msg, 192, FindAttr("alg", msg).AsString()); return(AES_KeyWrap(kwKey)); } case "ECDH-ES+A256KW": { if (key.AsString("kty") != "EC") { return(null); } byte[] secret = Ecdh(key, msg); byte[] kwKey = Kdf(secret, msg, 256, FindAttr("alg", msg).AsString()); return(AES_KeyWrap(kwKey)); } case "RSA1_5": { if (key.AsString("kty") != "RSA") { return(null); } IAsymmetricBlockCipher cipher = new Pkcs1Encoding(new RsaEngine()); RsaKeyParameters prv = new RsaPrivateCrtKeyParameters(key.AsBigInteger("n"), key.AsBigInteger("e"), key.AsBigInteger("d"), key.AsBigInteger("p"), key.AsBigInteger("q"), key.AsBigInteger("dp"), key.AsBigInteger("dq"), key.AsBigInteger("qi")); cipher.Init(false, prv); return(cipher.ProcessBlock(_rgbEncrypted, 0, _rgbEncrypted.Length)); } } return(null); }
public bool Verify(SignMessage msg) { string alg = FindAttribute("alg").AsString(); JWK key = keyToSign; IDigest digest; IDigest digest2; switch (alg) { case "RS256": case "ES256": case "PS256": case "HS256": digest = new Sha256Digest(); digest2 = new Sha256Digest(); break; case "RS384": case "ES384": case "PS384": case "HS384": digest = new Sha384Digest(); digest2 = new Sha384Digest(); break; case "RS512": case "ES512": case "PS512": case "HS512": digest = new Sha512Digest(); digest2 = new Sha512Digest(); break; case "EdDSA": digest = null; digest2 = null; break; default: throw new JoseException("Unknown signature algorithm"); } // byte[] toBeSigned; string str = ""; string body = Encoding.UTF8.GetString(msg.payloadB64); if (ProtectedMap.ContainsKey("b64") && ProtectedMap["b64"].AsBoolean() == false) { str += protectedB64 + "." + body; } else { str += protectedB64 + "." + body; } toBeSigned = Encoding.UTF8.GetBytes(str); switch (alg) { case "RS256": case "RS384": case "RS512": { if (key.AsString("kty") != "RSA") { throw new JoseException("Wrong Key"); } RsaDigestSigner signer = new RsaDigestSigner(digest); RsaKeyParameters pub = new RsaKeyParameters(false, key.AsBigInteger("n"), key.AsBigInteger("e")); signer.Init(false, pub); signer.BlockUpdate(toBeSigned, 0, toBeSigned.Length); if (!signer.VerifySignature(signature)) { throw new JoseException("Message failed to verify"); } } break; case "PS256": case "PS384": case "PS512": { PssSigner signer = new PssSigner(new RsaEngine(), digest, digest2, digest2.GetDigestSize()); RsaKeyParameters pub = new RsaKeyParameters(false, key.AsBigInteger("n"), key.AsBigInteger("e")); signer.Init(false, pub); signer.BlockUpdate(toBeSigned, 0, toBeSigned.Length); if (!signer.VerifySignature(signature)) { throw new JoseException("Message failed to verify"); } } break; case "ES256": case "ES384": case "ES512": { digest.BlockUpdate(toBeSigned, 0, toBeSigned.Length); byte[] o1 = new byte[digest.GetDigestSize()]; digest.DoFinal(o1, 0); if (key.AsString("kty") != "EC") { throw new JoseException("Wrong Key Type"); } ICipherParameters pubKey = keyToSign.AsPublicKey(); ECDsaSigner ecdsa = new ECDsaSigner(); ecdsa.Init(false, pubKey); BigInteger r = new BigInteger(1, signature, 0, signature.Length / 2); BigInteger s = new BigInteger(1, signature, signature.Length / 2, signature.Length / 2); if (!ecdsa.VerifySignature(o1, r, s)) { throw new JoseException("Signature did not validate"); } } break; case "HS256": case "HS384": case "HS512": { HMac hmac = new HMac(digest); KeyParameter K = new KeyParameter(Message.base64urldecode(key.AsString("k"))); hmac.Init(K); hmac.BlockUpdate(toBeSigned, 0, toBeSigned.Length); byte[] resBuf = new byte[hmac.GetMacSize()]; hmac.DoFinal(resBuf, 0); bool fVerify = true; for (int i = 0; i < resBuf.Length; i++) { if (resBuf[i] != signature[i]) { fVerify = false; } } if (!fVerify) { throw new JoseException("Signature did not validate"); } } break; case "EdDSA": { ISigner eddsa; if (key.AsString("kty") != "OKP") { throw new JoseException("Wrong Key Type"); } switch (key.AsString("crv")) { case "Ed25519": { Ed25519PublicKeyParameters privKey = new Ed25519PublicKeyParameters(key.AsBytes("X"), 0); eddsa = new Ed25519Signer(); eddsa.Init(false, privKey); eddsa.BlockUpdate(toBeSigned, 0, toBeSigned.Length); if (!eddsa.VerifySignature(signature)) { throw new JoseException("Signature did not validate"); } break; } default: throw new JoseException("Unknown algorithm"); } break; } default: throw new JoseException("Unknown algorithm"); } return(true); }
public void SetKey(JWK validateKey) { keyToSign = validateKey; }