Example #1
0
        private byte[] AESGCM_KeyWrap(byte[] key, EncryptMessage msg)
        {
            GcmBlockCipher cipher = new GcmBlockCipher(new AesEngine(), new BasicGcmMultiplier());
            KeyParameter   contentKey;

            //  The requirements from JWA
            //  IV is 96 bits
            //  Authentication tag is 128 bits
            //  key sizes are 128, 192 and 256 bits
            //  Keywrap says that there is no AAD

            contentKey = new KeyParameter(key);
            byte[] a   = new byte[0];
            byte[] iv  = Message.base64urldecode(FindAttr("iv", msg).AsString());
            byte[] tag = Message.base64urldecode(FindAttr("tag", msg).AsString());

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

            cipher.Init(false, parameters);
            byte[] c   = new byte[cipher.GetOutputSize(_rgbEncrypted.Length + tag.Length)];
            int    len = cipher.ProcessBytes(_rgbEncrypted, 0, _rgbEncrypted.Length, c, 0);

            len += cipher.ProcessBytes(tag, 0, tag.Length, c, len);
            cipher.DoFinal(c, len);

            return(c);
        }
Example #2
0
        private void ECDH_GenerateEphemeral(EncryptMessage msg)
        {
            CBORObject epk = CBORObject.NewMap();

            if (_mKey.AsString("kty") == "EC")
            {
                X9ECParameters     p          = NistNamedCurves.GetByName(_mKey.AsString("crv"));
                ECDomainParameters parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H);

                ECKeyPairGenerator        pGen     = new ECKeyPairGenerator();
                ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(parameters, Message.s_PRNG);
                pGen.Init(genParam);

                AsymmetricCipherKeyPair p1 = pGen.GenerateKeyPair();

                epk.Add("kty", "EC");
                epk.Add("crv", _mKey.AsString("crv"));
                ECPublicKeyParameters priv = (ECPublicKeyParameters)p1.Public;
                epk.Add("x", priv.Q.Normalize().XCoord.ToBigInteger().ToByteArrayUnsigned());
                epk.Add("y", priv.Q.Normalize().YCoord.ToBigInteger().ToByteArrayUnsigned());
            }
            else if (_mKey.AsString("kty") == "OKP")
            {
                switch (_mKey.AsString("crv"))
                {
                case "X25519":
                    Ed25519KeyPairGenerator        pGen     = new Ed25519KeyPairGenerator();
                    Ed25519KeyGenerationParameters genParam = new Ed25519KeyGenerationParameters(Message.s_PRNG);
                    pGen.Init(genParam);

                    AsymmetricCipherKeyPair    p1  = pGen.GenerateKeyPair();
                    Ed25519PublicKeyParameters pub = (Ed25519PublicKeyParameters)p1.Public;

                    epk.Add("kty", "OKP");
                    epk.Add("crv", "X25519");
                    epk.Add("x", pub.GetEncoded());
                    break;

                default:
                    throw new JoseException("Unknown OPK curve");
                }
            }
            else
            {
                throw new JoseException("Internal Error");
            }

            if (msg.FindAttribute(CBORObject.FromObject("epk"), PROTECTED) != null)
            {
                msg.AddAttribute(CBORObject.FromObject("epk"), epk, PROTECTED);
            }
            else if (msg.FindAttribute(CBORObject.FromObject("epk"), PROTECTED) != null)
            {
                msg.AddAttribute(CBORObject.FromObject("epk"), epk, PROTECTED);
            }
            else
            {
                AddAttribute("epk", epk, UNPROTECTED);
            }
        }
Example #3
0
        public static Message DecodeFromJSON(CBORObject message)
        {
            if (message.ContainsKey("ciphertext"))
            {
                EncryptMessage msgx = new EncryptMessage();
                msgx.InternalDecodeFromJSON(message);
                return(msgx);
            }

            SignMessage signMessage = new SignMessage();

            signMessage.InternalDecodeFromJSON(message);
            return(signMessage);
        }
Example #4
0
        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");
                }
            }
        }
Example #5
0
        public void Encrypt(EncryptMessage msg)
        {
            string alg; // Get the algorithm that was set.

            byte[]     rgbSecret;
            byte[]     rgbKey;
            CBORObject objSalt;
            CBORObject objIterCount;

            byte[] salt;
            byte[] saltInput;
            byte[] algBytes;

            alg = FindAttr("alg", msg).AsString();

            switch (alg)
            {
            case "dir":
            case "ECDH-ES":
            case "ECDH-SS":
                break;

            case "A128KW":
                AES_KeyWrap(128);
                break;

            case "A192KW":
                AES_KeyWrap(192);
                break;

            case "A256KW":
                AES_KeyWrap(256);
                break;

            case "RSA1_5":
                RSA_1_5_KeyWrap();
                break;

            case "RSA-OAEP":
                RSA_OAEP_KeyWrap(new Sha1Digest());
                break;

            case "RSA-OAEP-256":
                RSA_OAEP_KeyWrap(new Sha256Digest());
                break;

            case "ECDH-ES+A128KW":
                ECDH_GenerateEphemeral(msg);
                rgbSecret = ECDH_GenerateSecret(_mKey, msg);
                rgbKey    = Kdf(rgbSecret, msg, 128, alg);
                AES_KeyWrap(128, rgbKey);
                break;

            case "ECDH-ES+A192KW":
                ECDH_GenerateEphemeral(msg);
                rgbSecret = ECDH_GenerateSecret(_mKey, msg);
                rgbKey    = Kdf(rgbSecret, msg, 192, alg);
                AES_KeyWrap(192, rgbKey);
                break;

            case "ECDH-ES+A256KW":
                ECDH_GenerateEphemeral(msg);
                rgbSecret = ECDH_GenerateSecret(_mKey, msg);
                rgbKey    = Kdf(rgbSecret, msg, 256, alg);
                AES_KeyWrap(256, rgbKey);
                break;

            case "A128GCMKW":
                AES_GCM_KeyWrap(128, msg);
                break;

            case "A192GCMKW":
                AES_GCM_KeyWrap(192, msg);
                break;

            case "A256GCMKW":
                AES_GCM_KeyWrap(256, msg);
                break;

            case "PBES2-HS256+A128KW":
                objSalt = FindAttribute("p2s");
                if (objSalt == null)
                {
                    salt = new byte[10];
                    Message.s_PRNG.NextBytes(salt);
                    objSalt = CBORObject.FromObject(salt);
                    AddAttribute("p2s", objSalt, UNPROTECTED);
                }

                objIterCount = FindAttribute("p2c");
                if (objIterCount == null)
                {
                    objIterCount = CBORObject.FromObject(8000);
                    AddAttribute("p2c", objIterCount, UNPROTECTED);
                }

                saltInput = Message.base64urldecode(objSalt.AsString());
                algBytes  = Encoding.UTF8.GetBytes(alg);
                salt      = new byte[alg.Length + 1 + saltInput.Length];
                Array.Copy(algBytes, salt, algBytes.Length);
                Array.Copy(saltInput, 0, salt, algBytes.Length + 1, saltInput.Length);

                rgbKey = PBKDF2(_mKey.AsBytes("k"), salt, objIterCount.AsInt32(), 128 / 8, new Sha256Digest());
                AES_KeyWrap(128, rgbKey);
                break;

            case "PBES2-HS384+A192KW":
                objSalt = FindAttribute("p2s");
                if (objSalt == null)
                {
                    salt = new byte[10];
                    Message.s_PRNG.NextBytes(salt);
                    objSalt = CBORObject.FromObject(salt);
                    AddAttribute("p2s", objSalt, UNPROTECTED);
                }

                objIterCount = FindAttribute("p2c");
                if (objIterCount == null)
                {
                    objIterCount = CBORObject.FromObject(8000);
                    AddAttribute("p2c", objIterCount, UNPROTECTED);
                }

                saltInput = Message.base64urldecode(FindAttr("p2s", msg).AsString());
                algBytes  = Encoding.UTF8.GetBytes(alg);
                salt      = new byte[alg.Length + 1 + saltInput.Length];
                Array.Copy(algBytes, salt, algBytes.Length);
                Array.Copy(saltInput, 0, salt, algBytes.Length + 1, saltInput.Length);

                rgbKey = PBKDF2(_mKey.AsBytes("k"), salt, objIterCount.AsInt32(), 192 / 8, new Sha384Digest());
                AES_KeyWrap(192, rgbKey);
                break;

            case "PBES2-HS512+A256KW":
                objSalt = FindAttr("p2s", msg);
                if (objSalt == null)
                {
                    salt = new byte[10];
                    Message.s_PRNG.NextBytes(salt);
                    objSalt = CBORObject.FromObject(salt);
                    AddAttribute("p2s", objSalt, UNPROTECTED);
                }

                objIterCount = FindAttr("p2c", msg);
                if (objIterCount == null)
                {
                    objIterCount = CBORObject.FromObject(8000);
                    AddAttribute("p2c", objIterCount, UNPROTECTED);
                }

                saltInput = Message.base64urldecode(objSalt.AsString());
                algBytes  = Encoding.UTF8.GetBytes(alg);
                salt      = new byte[alg.Length + 1 + saltInput.Length];
                Array.Copy(algBytes, salt, algBytes.Length);
                Array.Copy(saltInput, 0, salt, algBytes.Length + 1, saltInput.Length);

                rgbKey = PBKDF2(_mKey.AsBytes("k"), salt, objIterCount.AsInt32(), 256 / 8, new Sha512Digest());
                AES_KeyWrap(256, rgbKey);
                break;

            default:
                throw new JoseException("Unknown or unsupported algorithm: " + alg);
            }
        }
Example #6
0
        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);
            }
        }
Example #7
0
        public byte[] GetKey(string alg, EncryptMessage msg)
        {
            if (_mKey == null)
            {
                return(null);
            }

            try {
                string keyAlgorithm = _mKey.AsString("alg");
                if (alg != keyAlgorithm)
                {
                    throw new JoseException("Algorithm mismatch between message and key");
                }
            }
            catch (Exception) {
                // ignored
            }

            //  Figure out how longer the needed key is:

            int cbitKey;

            switch (alg)
            {
            case "A128GCM":
            case "AES-128-CCM-64":
                cbitKey = 128;
                break;

            case "A192GCM":
                cbitKey = 196;
                break;

            case "A256GCM":
            case "HS256":
                cbitKey = 256;
                break;

            case "HS384":
                cbitKey = 384;
                break;

            case "HS512":
                cbitKey = 512;
                break;

            case "A128CBC-HS256":
                cbitKey = 128 * 2;
                break;

            case "A192CBC-HS256":
                cbitKey = 192 * 2;
                break;

            case "A256CBC-HS256":
                cbitKey = 256 * 2;
                break;

            default:
                throw new JoseException("NYI");
            }

            string algKeyManagement = FindAttr("alg", msg).AsString();

            switch (algKeyManagement)
            {
            case "dir":
                if (_mKey.AsString("kty") != "oct")
                {
                    throw new JoseException("Key and key managment algorithm don't match");
                }
                byte[] rgb = _mKey.AsBytes("k");
                if (rgb.Length * 8 != cbitKey)
                {
                    throw new JoseException("Incorrect key size");
                }
                return(rgb);

            case "ECDH-ES": {
                if ((_mKey.AsString("kty") != "EC") && (_mKey.AsString("kty") != "OKP"))
                {
                    throw new JoseException("Key and key management algorithm don't match");
                }

                ECDH_GenerateEphemeral(msg);

                byte[] rgbSecret = ECDH_GenerateSecret(_mKey, msg);

                return(Kdf(rgbSecret, msg, cbitKey, alg));
            }

            case "ECDH-SS": {
                if (_mKey.AsString("kty") != "EC")
                {
                    throw new JoseException("Key and key managment algorithm don't match");
                }
                if (FindAttribute("apu") == null)
                {
                    byte[] rgbApu = new byte[512 / 8];
                    Message.s_PRNG.NextBytes(rgbApu);
                    AddAttribute("apu", CBORObject.FromObject(rgbApu), UNPROTECTED);
                }

                byte[] rgbSecret = ECDH_GenerateSecret(_mKey, msg);
                return(Kdf(rgbSecret, msg, cbitKey, alg));
            }
            }

            throw new JoseException($"NYI: {alg}");
        }
Example #8
0
        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);
        }
Example #9
0
        private void AES_GCM_KeyWrap(int keySize, EncryptMessage msg)
        {
            if (_mKey.AsString("kty") != "oct")
            {
                throw new JoseException("Incorrect key type");
            }
            byte[] keyBytes = _mKey.AsBytes("k");
            if (keyBytes.Length != keySize / 8)
            {
                throw new JoseException("Key is not the correct size");
            }

            GcmBlockCipher cipher = new GcmBlockCipher(new AesEngine(), new BasicGcmMultiplier());
            KeyParameter   contentKey;

            //  The requirements from JWA
            //  IV is 96 bits
            //  Authentication tag is 128 bits
            //  key sizes are 128, 192 and 256 bits
            //  Keywrap says that there is no AAD

            contentKey = new KeyParameter(keyBytes);
            byte[] a  = new byte[0];
            byte[] iv = new byte[96 / 8];


            Message.s_PRNG.NextBytes(iv);
            if (msg.FindAttribute(CBORObject.FromObject("iv"), PROTECTED) != null)
            {
                msg.AddAttribute("iv", Message.base64urlencode(iv), PROTECTED);
            }
            else if (msg.FindAttribute(CBORObject.FromObject("iv"), UNPROTECTED) != null)
            {
                msg.AddAttribute("iv", Message.base64urlencode(iv), UNPROTECTED);
            }
            else
            {
                UnprotectedMap.Add("iv", Message.base64urlencode(iv));
            }

            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);

            len += cipher.DoFinal(c, len);

            if (len != c.Length)
            {
                throw new JoseException("NYI");
            }
            byte[] tag = new byte[128 / 8];
            Array.Copy(c, c.Length - tag.Length, tag, 0, tag.Length);

            if (msg.FindAttribute(CBORObject.FromObject("tag"), PROTECTED) != null)
            {
                msg.AddAttribute("tag", Message.base64urlencode(tag), PROTECTED);
            }
            else if (msg.FindAttribute(CBORObject.FromObject("tag"), UNPROTECTED) != null)
            {
                msg.AddAttribute("tag", Message.base64urlencode(tag), UNPROTECTED);
            }
            else
            {
                UnprotectedMap.Add("tag", Message.base64urlencode(tag));
            }

            _rgbEncrypted = c;
            Array.Resize(ref _rgbEncrypted, c.Length - tag.Length);
        }
Example #10
0
        private byte[] Kdf(byte[] secret, EncryptMessage msg, int cbitKey, string algorithmId)
        {
            //  Build a long byte array
            //  four byte counter
            //  secret
            //  AlgorithmID - [32-bit size || algorithm identifier ]
            //  PartyUInfo - [32-bit size || PartyUInfo ] ---- "apu"
            //  PartyVInfo - [32-bit size || PartyVInfo ] ---- "apv"
            //  SuppPubInfo - 32-bit - key data len
            //  SuppPrivInfo - nothing

            byte[] rgbPartyU = new byte[0];
            byte[] rgbPartyV = new byte[0];
            byte[] algId     = Encoding.UTF8.GetBytes(algorithmId);

            CBORObject j = FindAttr("apu", msg);

            if (j != null)
            {
                rgbPartyU = Message.base64urldecode(j.AsString());
            }

            j = FindAttr("apv", msg);
            if (j != null)
            {
                rgbPartyV = Message.base64urldecode(j.AsString());
            }

            int c = 4 + secret.Length + 4 + algId.Length + 4 + rgbPartyU.Length + 4 + rgbPartyV.Length + 4;

            byte[] rgb = new byte[c];

            //  Counter starts at 0

            Array.Copy(secret, 0, rgb, 4, secret.Length);
            c = 4 + secret.Length;

            if (algorithmId.Length > 255)
            {
                throw new JoseException("Internal error");
            }
            rgb[c + 3] = (byte)algId.Length;
            Array.Copy(algId, 0, rgb, c + 4, algId.Length);
            c += 4 + algorithmId.Length;

            if (rgbPartyU.Length > 255)
            {
                throw new JoseException("Internal error");
            }
            rgb[c + 3] = (byte)rgbPartyU.Length;
            Array.Copy(rgbPartyU, 0, rgb, c + 4, rgbPartyU.Length);
            c += 4 + rgbPartyU.Length;

            if (rgbPartyV.Length > 255)
            {
                throw new JoseException("internal error");
            }
            rgb[c + 3] = (byte)rgbPartyV.Length;
            Array.Copy(rgbPartyV, 0, rgb, c + 4, rgbPartyV.Length);
            c += 4 + rgbPartyV.Length;

            if (cbitKey / (256 * 256) != 0)
            {
                throw new JoseException("internal error");
            }
            rgb[c + 3] = (byte)(cbitKey % 256);
            rgb[c + 2] = (byte)(cbitKey / 256);

            //  Now do iterative hashing

            IDigest digest = new Sha256Digest();
            int     cIters = (cbitKey + 255) / 256;

            byte[] rgbDigest = new byte[256 / 8 * cIters];

            for (int i = 0; i < cIters; i++)
            {
                rgb[3] = (byte)(i + 1);
                digest.Reset();
                digest.BlockUpdate(rgb, 0, rgb.Length);
                digest.DoFinal(rgbDigest, (256 / 8) * i);
            }

            byte[] rgbOut = new byte[cbitKey / 8];
            Array.Copy(rgbDigest, rgbOut, rgbOut.Length);
            return(rgbOut);
        }