Example #1
0
        public CBORObject EncodeToJSON(byte[] body)
        {
            CBORObject obj = CBORObject.NewMap();

            if (protectedB64 != null)
            {
                obj.Add("protected", protectedB64);
            }
            else if (ProtectedMap.Count > 0)
            {
                protectedB64 = Message.base64urlencode(Encoding.UTF8.GetBytes(JSON.ToJsonString(ProtectedMap)));
                obj.Add("protected", protectedB64);
            }

            if (UnprotectedMap.Count > 0)
            {
                obj.Add("header", UnprotectedMap);                           // Add unprotected attributes
            }
            String str = "";

            if (ProtectedMap.ContainsKey("b64") && ProtectedMap["b64"].AsBoolean() == false)
            {
                str += protectedB64 + "." + Encoding.UTF8.GetString(body);
            }
            else
            {
                str += protectedB64 + "." + Message.base64urlencode(body);
            }

#if DEBUG
            ToBeSigned = str;
#endif

            obj.Add("signature", Message.base64urlencode(Sign(Encoding.UTF8.GetBytes(str))));

            return(obj);
        }
Example #2
0
        /// <summary>
        /// Encrypt the message based on attributes and recipients.
        /// </summary>
        public virtual void Encrypt()
        {
            string alg = null;

            //  Get the algorithm we are using - the default is AES GCM

            try {
                alg = FindAttribute("enc").AsString();
            }
            catch {
                foreach (Recipient r in RecipientList)
                {
                    CBORObject alg2 = r.FindAttribute("enc");
                    if (alg2 != null)
                    {
                        if (alg2.Type != CBORType.TextString || (alg != null && alg != alg2.AsString()))
                        {
                            throw new JoseException("Multiple content encryption algorithms have been specified.");
                        }
                        alg = alg2.AsString();
                    }
                }

                if (alg == null)
                {
                    throw new JoseException("Content encryption algorithm has not been specified.");
                }
            }

            byte[] contentKey = null;

            //  Determine if we are doing a direct encryption
            int recipientTypes = 0;

            if (RecipientList.Count == 0)
            {
                throw new JoseException("Must have at least one recipient for the message");
            }

            foreach (Recipient key in RecipientList)
            {
                switch (key.RecipientType)
                {
                case RecipientType.Direct:
                case RecipientType.KeyAgreeDirect:
                    if ((recipientTypes & 1) != 0)
                    {
                        throw new JoseException("It is not legal to have two direct recipients in a message");
                    }
                    recipientTypes |= 1;
                    contentKey      = key.GetKey(alg, this);
                    break;

                default:
                    recipientTypes |= 2;
                    break;
                }
            }

            if (recipientTypes == 3)
            {
                throw new JoseException("It is not legal to mix direct and indirect recipients in a message");
            }

            if (contentKey == null)
            {
                switch (alg)
                {
                case "A128GCM":
                case "AES-128-CCM-64":
                    contentKey = new byte[128 / 8];
                    break;

                case "A192GCM":
                case "AES192GCM":
                    contentKey = new byte[192 / 8];
                    break;

                case "A256GCM":
                case "AES256GCM":
                    contentKey = new byte[256 / 8];
                    break;

                case "A128CBC-HS256":
                    contentKey = new byte[2 * 128 / 8];
                    break;

                case "A192CBC-HS256":
                    contentKey = new byte[2 * 192 / 8];
                    break;

                case "A256CBC-HS256":
                    contentKey = new byte[2 * 256 / 8];
                    break;

                default:
                    throw new JoseException($"Unrecognized content encryption algorithm '{alg}'");
                }

                s_PRNG.NextBytes(contentKey);
            }

            foreach (Recipient key in RecipientList)
            {
                key.SetContent(contentKey);
                key.Encrypt(this);
            }

            //  Encode the protected attributes if there are any

            if (ProtectedMap.Count > 0)
            {
                _strProtected = base64urlencode(Encoding.UTF8.GetBytes(ProtectedMap.ToString()));
            }

            byte[] saveContent = payload;
            if (ProtectedMap.ContainsKey("zip"))
            {
                MemoryStream  stm2   = new MemoryStream();
                DeflateStream zipStm = new DeflateStream(stm2, CompressionMode.Compress);

                zipStm.Write(payload, 0, payload.Length);
                zipStm.Close();

                payload = stm2.GetBuffer();
            }

            switch (alg)
            {
            case "A128GCM":
            case "A192GCM":
            case "A256GCM":
                AES_GCM_Encrypt(contentKey);
                break;

            case "AES-128-CCM-64":
                AES_CCM(contentKey);
                break;

            case "A128CBC-HS256":
            case "A192CBC-HS256":
            case "A256CBC-HS256":
                AES_CBC_MAC_Encrypt(alg, contentKey);
                break;

            default:
                throw new JoseException("Internal Error:  We should never get here.");
            }

            payload = saveContent;
        }
Example #3
0
        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);
        }