Exemplo n.º 1
0
        private void AES_CCM(byte[] k)
        {
            CcmBlockCipher cipher = new CcmBlockCipher(new AesEngine());
            KeyParameter   contentKey;
            int            cbitTag = 64;

            //  The requirements from JWA
            //  IV is 96 bits
            //  Authentication tag is 128 bits
            //  key sizes are 128, 192 and 256 bits

            _iv = new byte[96 / 8];
            s_PRNG.NextBytes(_iv);

            contentKey = new KeyParameter(k);

            //  Build the object to be hashed

            byte[] a = new byte[0];
            if (ProtectedMap != null)
            {
                a = Encoding.UTF8.GetBytes(ProtectedMap.ToString());
            }

            AeadParameters parameters = new AeadParameters(contentKey, 128, _iv, a);

            cipher.Init(true, parameters);

            byte[] c   = new byte[cipher.GetOutputSize(payload.Length)];
            int    len = cipher.ProcessBytes(payload, 0, payload.Length, c, 0);

            cipher.DoFinal(c, len);

            Array.Resize(ref c, c.Length - (128 / 8) + (cbitTag / 8));
            _RgbEncrypted = c;
        }
Exemplo n.º 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;
        }
Exemplo n.º 3
0
        /// <inheritdoc />
        protected override CBORObject InternalEncodeToJSON(bool fCompact)
        {
            CBORObject obj = CBORObject.NewMap();

            if (_RgbEncrypted == null)
            {
                Encrypt();
            }

            if (ProtectedMap.Count > 0)
            {
                obj.Add("protected", base64urlencode(Encoding.UTF8.GetBytes(ProtectedMap.ToString())));
            }

            if (UnprotectedMap.Count > 0)
            {
                obj.Add("unprotected", UnprotectedMap);                           // Add unprotected attributes
            }
            if (_iv != null)
            {
                obj.Add("iv", base64urlencode(_iv));                     // Add iv
            }
            if (_Aad != null)
            {
                obj.Add("aad", Encoding.UTF8.GetString(_Aad));
            }

            if (_RgbEncrypted != null)
            {
                obj.Add("ciphertext", base64urlencode(_RgbEncrypted));                             // Add ciphertext
            }
            obj.Add("tag", base64urlencode(_Tag));

            if (RecipientList.Count > 0)
            {
                CBORObject recipients = CBORObject.NewArray();

                foreach (Recipient key in RecipientList)
                {
                    CBORObject j = key.EncodeToJSON();
                    if ((j != null) && (j.Count != 0))
                    {
                        recipients.Add(j);
                    }
                }

                if (fCompact)
                {
                    if (recipients.Count != 1)
                    {
                        throw new JoseException("Compact encoding must be for one recipient");
                    }
                    if (recipients[0].ContainsKey("encrypted_key"))
                    {
                        obj.Add("encrypted_key", recipients[0]["encrypted_key"]);
                    }

                    if (recipients[0].ContainsKey("header"))
                    {
                        obj.Add("header", recipients[0]["header"]);
                    }
                }
                else
                {
                    if (recipients.Count > 0)
                    {
                        obj.Add("recipients", recipients);
                    }
                }
            }
            else
            {
                throw new JoseException("Must have one or more recipients");
            }
            return(obj);
        }