예제 #1
0
        /// <summary>
        /// Given the set of inputs, perform the crptographic operations that are needed
        /// to build a security context for a single sender and recipient.
        /// </summary>
        /// <param name="masterSecret">pre-shared key</param>
        /// <param name="entityId">name assigned to sender</param>
        /// <param name="masterSalt">salt value</param>
        /// <param name="algAEAD">encryption algorithm</param>
        /// <param name="algKeyAgree">key agreement algorithm</param>
        /// <returns></returns>
        private static EntityContext DeriveEntityContext(byte[] masterSecret, byte[] entityId, byte[] masterSalt = null, CBORObject algAEAD = null, CBORObject algKeyAgree = null)
        {
            EntityContext ctx = new EntityContext();

            ctx.Algorithm = algAEAD ?? AlgorithmValues.AES_CCM_64_64_128;
            ctx.Id        = entityId ?? throw new ArgumentNullException(nameof(entityId));
            if (algKeyAgree == null)
            {
                algKeyAgree = AlgorithmValues.ECDH_SS_HKDF_256;
            }

            ctx.ReplayWindow = new ReplayWindow(0, 64);

            CBORObject info = CBORObject.NewArray();

            // M00TODO - add the group id into this

            info.Add(entityId);                 // 0
            info.Add(ctx.Algorithm);            // 1
            info.Add("Key");                    // 2
            info.Add(128 / 8);                  // 3 in bytes


            IDigest sha256;

            if (algKeyAgree == null || algKeyAgree.Equals(AlgorithmValues.ECDH_SS_HKDF_256))
            {
                sha256 = new Sha256Digest();
            }
            else if (algKeyAgree.Equals(AlgorithmValues.ECDH_SS_HKDF_512))
            {
                sha256 = new Sha512Digest();
            }
            else
            {
                throw new ArgumentException("Unknown key agree algorithm");
            }

            IDerivationFunction hkdf = new HkdfBytesGenerator(sha256);

            hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes()));

            ctx.Key = new byte[128 / 8];
            hkdf.GenerateBytes(ctx.Key, 0, ctx.Key.Length);

            info[2] = CBORObject.FromObject("IV");
            info[3] = CBORObject.FromObject(56 / 8);
            hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes()));
            ctx.BaseIV = new byte[56 / 8];
            hkdf.GenerateBytes(ctx.BaseIV, 0, ctx.BaseIV.Length);

            return(ctx);
        }
예제 #2
0
        // Tests the equivalence of the DecodeFromBytes and Read methods.
        public static CBORObject FromBytesTestAB(byte[] b)
        {
            CBORObject oa = FromBytesA(b);
            CBORObject ob = FromBytesB(b);

            if (!oa.Equals(ob))
            {
                Assert.AreEqual(oa, ob);
            }
            return(oa);
        }
예제 #3
0
        // Tests the equivalence of the DecodeFromBytes and Read methods.
        public static CBORObject FromBytesTestAB(byte[] b, CBOREncodeOptions
                                                 options)
        {
            CBORObject oa = FromBytesA(b, options);
            CBORObject ob = FromBytesB(b, options);

            if (!oa.Equals(ob))
            {
                Assert.AreEqual(oa, ob);
            }
            return(oa);
        }
예제 #4
0
        public CBORObject Lookup(CBORObject value)
        {
            foreach (KeyValuePair <int, string> o in _dictionary)
            {
                if (value.Equals(CBORObject.FromObject(o.Value)))
                {
                    CBORObject newValue = CBORObject.FromObject(o.Key);
                    if (value.Type == CBORType.Number)
                    {
                        newValue = CBORObject.FromObjectAndTag(newValue, DictionaryTag);
                    }

                    return(newValue);
                }
            }

            return(value);
        }
예제 #5
0
        public CBORObject Lookup(CBORObject value, bool isIntLegal)
        {
            if (value.Type == CBORType.TextString)
            {
                return(Lookup(value.AsString(), isIntLegal));
            }

            foreach (KeyValuePair <int, object> o in _dictionary)
            {
                if (value.Equals(o.Value))
                {
                    if (isIntLegal)
                    {
                        return(CBORObject.FromObjectAndTag(o.Key, DictionaryTag));
                    }

                    return(CBORObject.FromObject(o.Key));
                }
            }

            return(value);
        }
예제 #6
0
        /// <summary>
        /// Given the set of inputs, perform the crptographic operations that are needed
        /// to build a security context for a single sender and recipient.
        /// </summary>
        /// <param name="masterSecret">pre-shared key</param>
        /// <param name="senderId">name assigned to sender</param>
        /// <param name="recipientId">name assigned to recipient</param>
        /// <param name="masterSalt">salt value</param>
        /// <param name="algAEAD">encryption algorithm</param>
        /// <param name="algKeyAgree">key agreement algorithm</param>
        /// <returns></returns>
        public static SecurityContext DeriveContext(byte[] masterSecret, byte[] senderId, byte[] recipientId, byte[] masterSalt = null, CBORObject algAEAD = null, CBORObject algKeyAgree = null)
        {
            SecurityContext ctx = new SecurityContext();

            if (algAEAD == null)
            {
                ctx.Sender.Algorithm = AlgorithmValues.AES_CCM_64_64_128;
            }
            else
            {
                ctx.Sender.Algorithm = algAEAD;
            }
            ctx.Sender.Id = senderId ?? throw new ArgumentNullException(nameof(senderId));

            ctx.Recipient = new EntityContext {
                Algorithm = ctx.Sender.Algorithm,
                Id        = recipientId ?? throw new ArgumentNullException(nameof(recipientId)),
                                  ReplayWindow = new ReplayWindow(0, 64)
            };


            CBORObject info = CBORObject.NewArray();

            info.Add(senderId);             // 0
            info.Add(ctx.Sender.Algorithm); // 1
            info.Add("Key");                // 2
            info.Add(128 / 8);              // 3 in bytes

            IDigest sha256;

            if (algKeyAgree == null || algKeyAgree.Equals(AlgorithmValues.ECDH_SS_HKDF_256))
            {
                sha256 = new Sha256Digest();
            }
            else if (algKeyAgree.Equals(AlgorithmValues.ECDH_SS_HKDF_512))
            {
                sha256 = new Sha512Digest();
            }
            else
            {
                throw new ArgumentException("Unrecognized key agreement algorithm");
            }

            IDerivationFunction hkdf = new HkdfBytesGenerator(sha256);

            hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes()));

            ctx.Sender.Key = new byte[128 / 8];
            hkdf.GenerateBytes(ctx.Sender.Key, 0, ctx.Sender.Key.Length);

            info[0] = CBORObject.FromObject(recipientId);
            hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes()));
            ctx.Recipient.Key = new byte[128 / 8];
            hkdf.GenerateBytes(ctx.Recipient.Key, 0, ctx.Recipient.Key.Length);

            info[2] = CBORObject.FromObject("IV");
            info[3] = CBORObject.FromObject(56 / 8);
            hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes()));
            ctx.Recipient.BaseIV = new byte[56 / 8];
            hkdf.GenerateBytes(ctx.Recipient.BaseIV, 0, ctx.Recipient.BaseIV.Length);

            info[0] = CBORObject.FromObject(senderId);
            hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes()));
            ctx.Sender.BaseIV = new byte[56 / 8];
            hkdf.GenerateBytes(ctx.Sender.BaseIV, 0, ctx.Sender.BaseIV.Length);

            //  Give a unique context number for doing comparisons

            ctx.ContextNo   = _ContextNumber;
            _ContextNumber += 1;

            return(ctx);
        }
예제 #7
0
        public static JSONPointer FromPointer(CBORObject obj, string pointer)
        {
            var index = 0;

            if (pointer == null)
            {
                throw new ArgumentNullException(nameof(pointer));
            }
            if (pointer.Length == 0)
            {
                return(new JSONPointer(obj, pointer));
            }
            while (true)
            {
                if (obj == null)
                {
                    throw new ArgumentNullException(nameof(obj));
                }
                if (obj.Type == CBORType.Array)
                {
                    if (index >= pointer.Length || pointer[index] != '/')
                    {
                        throw new ArgumentException(pointer);
                    }
                    ++index;
                    var value    = new int[] { 0 };
                    int newIndex = ReadPositiveInteger(pointer, index, value);
                    if (value[0] < 0)
                    {
                        if (index < pointer.Length && pointer[index] == '-' &&
                            (index + 1 == pointer.Length || pointer[index + 1] == '/'))
                        {
                            // Index at the end of the array
                            return(new JSONPointer(obj, "-"));
                        }
                        throw new ArgumentException(pointer);
                    }
                    if (newIndex == pointer.Length)
                    {
                        return(new JSONPointer(obj, pointer.Substring(index)));
                    }
                    else
                    {
                        obj   = obj[value[0]];
                        index = newIndex;
                    }
                    index = newIndex;
                }
                else if (obj.Type == CBORType.Map)
                {
                    if (obj.Equals(CBORObject.Null))
                    {
                        throw new KeyNotFoundException(pointer);
                    }
                    if (index >= pointer.Length || pointer[index] != '/')
                    {
                        throw new ArgumentException(pointer);
                    }
                    ++index;
                    string key      = null;
                    int    oldIndex = index;
                    var    tilde    = false;
                    while (index < pointer.Length)
                    {
                        int c = pointer[index];
                        if (c == '/')
                        {
                            break;
                        }
                        if (c == '~')
                        {
                            tilde = true;
                            break;
                        }
                        ++index;
                    }
                    if (!tilde)
                    {
                        key = pointer.Substring(
                            oldIndex,
                            index - oldIndex);
                    }
                    else
                    {
                        index = oldIndex;
                        var sb = new StringBuilder();
                        while (index < pointer.Length)
                        {
                            int c = pointer[index];
                            if (c == '/')
                            {
                                break;
                            }
                            if (c == '~')
                            {
                                if (index + 1 < pointer.Length)
                                {
                                    if (pointer[index + 1] == '1')
                                    {
                                        index += 2;
                                        sb.Append('/');
                                        continue;
                                    }
                                    else if (pointer[index + 1] == '0')
                                    {
                                        index += 2;
                                        sb.Append('~');
                                        continue;
                                    }
                                }
                                throw new ArgumentException(pointer);
                            }
                            else
                            {
                                sb.Append((char)c);
                            }
                            ++index;
                        }
                        key = sb.ToString();
                    }
                    if (index == pointer.Length)
                    {
                        return(new JSONPointer(obj, key));
                    }
                    else
                    {
                        obj = ((CBORObject)obj)[key];
                    }
                }
                else
                {
                    throw new KeyNotFoundException(pointer);
                }
            }
        }
예제 #8
0
파일: TestFiles.cs 프로젝트: lulzzz/CWT
        OneKey LoadKey(CBORObject obj)
        {
            OneKey     newKey = new OneKey();
            CBORObject kty;

            switch (obj["kty"].AsString())
            {
            case "oct":
                kty = GeneralValues.KeyType_Octet;
                break;

            case "EC":
                kty = GeneralValues.KeyType_EC;
                break;

            default:
                throw new Exception("Unknown key type " + obj["cty"].AsString());
            }

            foreach (CBORObject key in obj.Keys)
            {
                CBORObject value = obj[key];
                CBORObject key2  = key;

                if (key.AsString().EndsWith("_hex"))
                {
                    value = CBORObject.FromObject(FromHex(value.AsString()));
                    key2  = CBORObject.FromObject(key.AsString().Substring(0, key.AsString().Length - 4));
                }

                key2 = MapKey(key2);
                if (key2.Equals(CoseKeyKeys.KeyType))
                {
                    value = kty;
                }
                else if (key2.Equals(CoseKeyKeys.KeyIdentifier))
                {
                    value = CBORObject.FromObject(Encoding.UTF8.GetBytes(value.AsString()));
                }
                else if (key2.Equals(CoseKeyKeys.Algorithm))
                {
                    value = MapAlgorithm(value.AsString());
                }
                else if (kty.Equals(GeneralValues.KeyType_EC) && key2.Equals(CoseKeyParameterKeys.EC_Curve))
                {
                    switch (value.AsString())
                    {
                    case "P-256":
                        value = GeneralValues.P256;
                        break;

                    default:
                        throw new Exception("Unknown curve " + value.AsString());
                    }
                }

                newKey.Add(key2, value);
            }

            return(newKey);
        }
예제 #9
0
        /// <summary>
        /// Given the set of inputs, perform the crptographic operations that are needed
        /// to build a security context for a single sender and recipient.
        /// </summary>
        /// <param name="masterSecret">pre-shared key</param>
        /// <param name="groupId">Group/Context Identifier</param>
        /// <param name="entityId">name assigned to sender</param>
        /// <param name="masterSalt">salt value</param>
        /// <param name="algAEAD">encryption algorithm</param>
        /// <param name="algKeyAgree">key agreement algorithm</param>
        /// <returns></returns>
        private static EntityContext DeriveEntityContext(byte[] masterSecret, byte[] groupId, byte[] entityId, byte[] masterSalt = null, CBORObject algAEAD = null, CBORObject algKeyAgree = null)
        {
            EntityContext ctx = new EntityContext();
            int           keySize;
            int           ivSize;

            ctx.Algorithm = algAEAD ?? AlgorithmValues.AES_CCM_16_64_128;
            ctx.Id        = entityId ?? throw new ArgumentNullException(nameof(entityId));
            if (algKeyAgree == null)
            {
                algKeyAgree = AlgorithmValues.ECDH_SS_HKDF_256;
            }

            if (ctx.Algorithm.Type != CBORType.Number)
            {
                throw new ArgumentException("algorithm is unknown");
            }
            switch ((AlgorithmValuesInt)ctx.Algorithm.AsInt32())
            {
            case AlgorithmValuesInt.AES_CCM_16_64_128:
                keySize = 128 / 8;
                ivSize  = 13;
                break;

            case AlgorithmValuesInt.AES_GCM_128:
                keySize = 128 / 8;
                ivSize  = 96 / 8;
                break;

            default:
                throw new ArgumentException("algorithm is unknown");
            }

            ctx.ReplayWindow = new ReplayWindow(0, 64);

            CBORObject info = CBORObject.NewArray();

            // M00TODO - add the group id into this

            info.Add(entityId);                 // 0
            info.Add(groupId);                  // 1
            info.Add(ctx.Algorithm);            // 2
            info.Add("Key");                    // 3
            info.Add(keySize);                  // 4 in bytes


            IDigest sha256;

            if (algKeyAgree == null || algKeyAgree.Equals(AlgorithmValues.ECDH_SS_HKDF_256))
            {
                sha256 = new Sha256Digest();
            }
            else if (algKeyAgree.Equals(AlgorithmValues.ECDH_SS_HKDF_512))
            {
                sha256 = new Sha512Digest();
            }
            else
            {
                throw new ArgumentException("Unknown key agree algorithm");
            }

            IDerivationFunction hkdf = new HkdfBytesGenerator(sha256);

            hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes()));

            ctx.Key = new byte[keySize];
            hkdf.GenerateBytes(ctx.Key, 0, ctx.Key.Length);

            info[0] = CBORObject.FromObject(new byte[0]);
            info[3] = CBORObject.FromObject("IV");
            info[4] = CBORObject.FromObject(ivSize);
            hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes()));
            ctx.BaseIV = new byte[ivSize];
            hkdf.GenerateBytes(ctx.BaseIV, 0, ctx.BaseIV.Length);

            // Modify the context

            if (ivSize - 6 < entityId.Length)
            {
                throw new CoAPException("Entity id is too long");
            }
            ctx.BaseIV[0] ^= (byte)entityId.Length;
            int i1 = ivSize - 5 - entityId.Length /*- 1*/;

            for (int i = 0; i < entityId.Length; i++)
            {
                ctx.BaseIV[i1 + i] ^= entityId[i];
            }

            return(ctx);
        }
예제 #10
0
        /// <summary>
        /// Given the set of inputs, perform the crptographic operations that are needed
        /// to build a security context for a single sender and recipient.
        /// </summary>
        /// <param name="masterSecret">pre-shared key</param>
        /// <param name="senderContext">context for the ID</param>
        /// <param name="senderId">name assigned to sender</param>
        /// <param name="recipientId">name assigned to recipient</param>
        /// <param name="masterSalt">salt value</param>
        /// <param name="algAEAD">encryption algorithm</param>
        /// <param name="algKeyAgree">key agreement algorithm</param>
        /// <returns></returns>
        public static SecurityContext DeriveContext(byte[] masterSecret, byte[] senderContext, byte[] senderId, byte[] recipientId,
                                                    byte[] masterSalt = null, CBORObject algAEAD = null, CBORObject algKeyAgree = null)
        {
            int             cbKey;
            int             cbIV;
            SecurityContext ctx = new SecurityContext();

            if (algAEAD == null)
            {
                ctx.Sender.Algorithm = AlgorithmValues.AES_CCM_16_64_128;
            }
            else
            {
                ctx.Sender.Algorithm = algAEAD;
            }

            if (ctx.Sender.Algorithm.Type != CBORType.Number)
            {
                throw new CoAPException("Unsupported algorithm");
            }
            switch ((AlgorithmValuesInt)ctx.Sender.Algorithm.AsInt32())
            {
            case AlgorithmValuesInt.AES_CCM_16_64_128:
                cbKey = 128 / 8;
                cbIV  = 13;
                break;

            case AlgorithmValuesInt.AES_CCM_64_64_128:
                cbKey = 128 / 8;
                cbIV  = 56 / 8;
                break;

            case AlgorithmValuesInt.AES_CCM_64_128_128:
                cbKey = 128 / 8;
                cbIV  = 56 / 8;
                break;

            case AlgorithmValuesInt.AES_CCM_16_128_128:
                cbKey = 128 / 8;
                cbIV  = 13;
                break;

            case AlgorithmValuesInt.AES_GCM_128:
                cbKey = 128 / 8;
                cbIV  = 96 / 8;
                break;

            default:
                throw new CoAPException("Unsupported algorithm");
            }

            ctx.Sender.Id = senderId ?? throw new ArgumentNullException(nameof(senderId));

            ctx.Recipient = new EntityContext {
                Algorithm = ctx.Sender.Algorithm,
                Id        = recipientId ?? throw new ArgumentNullException(nameof(recipientId)),
                                  ReplayWindow = new ReplayWindow(0, 64)
            };


            CBORObject info = CBORObject.NewArray();

            info.Add(senderId);             // 0
            info.Add(senderContext);        // 1
            info.Add(ctx.Sender.Algorithm); // 2
            info.Add("Key");                // 3
            info.Add(cbKey);                // 4 in bytes

            IDigest sha256;

            if (algKeyAgree == null || algKeyAgree.Equals(AlgorithmValues.ECDH_SS_HKDF_256))
            {
                sha256 = new Sha256Digest();
            }
            else if (algKeyAgree.Equals(AlgorithmValues.ECDH_SS_HKDF_512))
            {
                sha256 = new Sha512Digest();
            }
            else
            {
                throw new ArgumentException("Unrecognized key agreement algorithm");
            }

            IDerivationFunction hkdf = new HkdfBytesGenerator(sha256);

            hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes()));

            ctx.Sender.Key = new byte[cbKey];
            hkdf.GenerateBytes(ctx.Sender.Key, 0, ctx.Sender.Key.Length);

            info[0] = CBORObject.FromObject(recipientId);
            hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes()));
            ctx.Recipient.Key = new byte[cbKey];
            hkdf.GenerateBytes(ctx.Recipient.Key, 0, ctx.Recipient.Key.Length);

            info[0] = CBORObject.FromObject(new byte[0]);
            info[3] = CBORObject.FromObject("IV");
            info[4] = CBORObject.FromObject(cbIV);
            hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes()));
            ctx.Recipient.BaseIV = new byte[cbIV];
            hkdf.GenerateBytes(ctx.Recipient.BaseIV, 0, ctx.Recipient.BaseIV.Length);
            ctx.Sender.BaseIV = (byte[])ctx.Recipient.BaseIV.Clone();

            int iIv = cbIV - 5 - senderId.Length;

            if (cbIV - 6 < senderId.Length)
            {
                throw new CoAPException("Sender Id too long");
            }
            ctx.Sender.BaseIV[0] ^= (byte)senderId.Length;
            for (int i = 0; i < senderId.Length; i++)
            {
                ctx.Sender.BaseIV[iIv + i] ^= senderId[i];
            }

            iIv = cbIV - 5 - recipientId.Length;
            if (cbIV - 6 < recipientId.Length)
            {
                throw new CoAPException("Recipient Id too long");
            }
            ctx.Recipient.BaseIV[0] ^= (byte)recipientId.Length;
            for (int i = 0; i < recipientId.Length; i++)
            {
                ctx.Recipient.BaseIV[iIv + i] ^= recipientId[i];
            }

            //  Give a unique context number for doing comparisons

            ctx.ContextNo   = _contextNumber;
            _contextNumber += 1;

            return(ctx);
        }