예제 #1
0
        public static CBORObject RandomCBORArray(RandomGenerator rand, int depth)
        {
            int        x       = rand.UniformInt(100);
            int        count   = (x < 80) ? 2 : ((x < 93) ? 1 : ((x < 98) ? 0 : 10));
            CBORObject cborRet = CBORObject.NewArray();

            for (var i = 0; i < count; ++i)
            {
                cborRet.Add(RandomCBORObject(rand, depth + 1));
            }
            return(cborRet);
        }
예제 #2
0
        private byte[] BuildContentBytes()
#endif
        {
            CBORObject obj = CBORObject.NewArray();

            obj.Add(strContext);
            if (objProtected.Count > 0)
            {
                obj.Add(objProtected.EncodeToBytes());
            }
            else
            {
                obj.Add(CBORObject.FromObject(new byte[0]));
            }
            if (externalData != null)
            {
                obj.Add(CBORObject.FromObject(externalData));
            }
            else
            {
                obj.Add(CBORObject.FromObject(new byte[0]));
            }
            obj.Add(rgbContent);

            return(obj.EncodeToBytes());
        }
예제 #3
0
        private static void SerializeAttribute(string name, List <string> values, CBORObject cbor, Dictionary <string, CBORObject> dictionary)
        {
            bool       useSpace = SpaceSeparatedValueAttributes.Contains(name);
            CBORObject result;

            if (useSpace && values.Count > 1)
            {
                StringBuilder sb = new StringBuilder();

                foreach (string value in values)
                {
                    sb.Append(value);
                    sb.Append(" ");
                }
                sb.Length = sb.Length - 1;

                result = CBORObject.FromObject(sb.ToString());
            }
            else if (values.Count == 1)
            {
                string value = values.First();
                if (string.IsNullOrEmpty(value))
                {
                    result = CBORObject.True;
                }
                else
                {
                    result = CBORObject.FromObject(values.First());
                }
            }
            else
            {
                result = CBORObject.NewArray();
                foreach (string value in values)
                {
                    if (string.IsNullOrEmpty(value))
                    {
                        result.Add(CBORObject.True);
                    }
                    else
                    {
                        result.Add(value);
                    }
                }
            }

            CBORObject pair = CBORObject.NewArray();

            pair.Add(name);
            pair.Add(result);
            cbor.Add(pair);
        }
예제 #4
0
        public byte[] getAADBytes()
        {
            CBORObject obj = CBORObject.NewArray();

            obj.Add(_context);
            if (ProtectedMap.Count == 0)
            {
                ProtectedBytes = new byte[0];
            }
            else
            {
                ProtectedBytes = ProtectedMap.EncodeToBytes();
            }

            obj.Add(ProtectedBytes);

            obj.Add(CBORObject.FromObject(ExternalData));

            // Console.WriteLine("COSE AAD = " + BitConverter.ToString(obj.EncodeToBytes()));

            return(obj.EncodeToBytes());
        }
예제 #5
0
        public void codeWrongCount()
        {
            CBORObject obj = CBORObject.NewArray();

            obj.Add(CBORObject.False);


            byte[]        rgb = obj.EncodeToBytes();
            CoseException e   = Assert.ThrowsException <CoseException>(() =>
                                                                       Message.DecodeFromBytes(rgb, Tags.Sign1));

            Assert.AreEqual(e.Message, ("Invalid Sign1 structure"));
        }
예제 #6
0
        public void signerDecodeWrongCount()
        {
            CBORObject obj = CBORObject.NewArray();

            obj.Add(CBORObject.False);


            Signer        sig = new Signer();
            CoseException e   = Assert.ThrowsException <CoseException>(() =>
                                                                       sig.DecodeFromCBORObject(obj));

            Assert.AreEqual(e.Message, ("Invalid Signer structure"));
        }
예제 #7
0
        public CBORObject EncodeToCBOR(CBORObject fieldArray, Cori baseCori, CoralDictionary dictionary)
        {
            fieldArray.Add(dictionary.Lookup(FieldType, false));

            if (Literal != null)
            {
                fieldArray.Add(dictionary.Lookup(Literal, true));
            }
            else
            {
                CBORObject x = dictionary.Lookup(Url, true);
                if (x.Type == CBORType.Integer)
                {
                    fieldArray.Add(x);
                }
                else
                {
                    fieldArray.Add(Url.MakeRelative(baseCori).Data);
                }
            }

            return(fieldArray);
        }
예제 #8
0
        private byte[] toBeSigned()
        {
            CBORObject cborProtected = CBORObject.FromObject(new byte[0]);

            if ((ProtectedMap != null) && (ProtectedMap.Count > 0))
            {
                byte[] rgb = ProtectedMap.EncodeToBytes();
                cborProtected = CBORObject.FromObject(rgb);
            }

            CBORObject signObj = CBORObject.NewArray();

            signObj.Add(_context);
            signObj.Add(cborProtected);
            signObj.Add(ExternalData); // External AAD
            signObj.Add(rgbContent);

#if FOR_EXAMPLES
            m_toBeSigned = signObj.EncodeToBytes();
#endif

            return(signObj.EncodeToBytes());
        }
예제 #9
0
        private static void KdcJoin(string[] cmds)
        {
            if (cmds.Length != 3)
            {
                Console.WriteLine("Incorrect number of parameters");
                return;
            }

            if ((Program._CurrentOscore == null) || (Program._CurrentOscore.UserData == null) ||
                !(Program._CurrentOscore.UserData is GroupData))
            {
                Console.WriteLine("Can't use the current OSCORE context");
                return;
            }

            GroupData groupData = (GroupData)Program._CurrentOscore.UserData;

            OneKey signKey = OneKey.GenerateKey(null, GeneralValues.KeyType_OKP, "Ed25519");

            byte[] signature = Signer.Sign(groupData.SignNonce, groupData.SignInfo[0], signKey);

            CBORObject join = CBORObject.NewMap();
            CBORObject j2   = CBORObject.NewMap();

            j2.Add(Confirmation.ConfirmationIds.COSE_Key, signKey.AsCBOR());

            join.Add("type", 1);
            join.Add("client_cred", j2);
            join.Add("client_cred_verify", signature);

            Request request = new Request(Method.POST)
            {
                URI           = new Uri(cmds[1]),
                Payload       = @join.EncodeToBytes(),
                ContentType   = MediaType.ApplicationCbor,
                OscoreContext = Program._CurrentOscore
            };


            request.Send();
            Response response = request.WaitForResponse();

            if (response == null || response.StatusCode != StatusCode.Changed)
            {
                Console.WriteLine("Error in the response");
                return;
            }

            CBORObject respBody = CBORObject.DecodeFromBytes(response.Payload);
        }
예제 #10
0
        private byte[] toBeSigned(byte[] rgbContent, byte[] bodyAttributes)
        {
            CBORObject cborProtected = CBORObject.FromObject(new byte[0]);

            if ((objProtected != null) && (objProtected.Count > 0))
            {
                byte[] rgb = objProtected.EncodeToBytes();
                cborProtected = CBORObject.FromObject(rgb);
            }

            CBORObject signObj = CBORObject.NewArray();

            signObj.Add(context);
            signObj.Add(bodyAttributes);
            signObj.Add(cborProtected);
            signObj.Add(externalData);
            signObj.Add(rgbContent);

#if FOR_EXAMPLES
            m_toBeSigned = signObj.EncodeToBytes();
#endif
            return(signObj.EncodeToBytes());
        }
예제 #11
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);
        }
예제 #12
0
        public byte[] CreateMessage3()
        {
            CBORObject msg = CBORObject.NewArray();

            if (_fSymmetricSecret)
            {
                msg.Add(6);
            }
            else
            {
                msg.Add(3);
            }
            msg.Add(_SessionId[1]);

            byte[] aad_3 = ConcatenateAndHash(new byte[2][] { _LastMessageAuthenticator, msg.EncodeToBytes() }, _MessageDigest);

            byte[] signBody = new byte[0];
            if (!_fSymmetricSecret)
            {
                Sign1Message sign1 = new Sign1Message(false, false);
                sign1.SetContent(aad_3);
                sign1.AddAttribute(HeaderKeys.Algorithm, _algSign, Attributes.DO_NOT_SEND);
                sign1.AddAttribute(HeaderKeys.KeyId, _SigningKey[CoseKeyKeys.KeyIdentifier], Attributes.UNPROTECTED);
                sign1.Sign(_SigningKey);

                CBORObject obj = CBORObject.NewArray();
                obj.Add(sign1.EncodeToBytes());

                signBody = obj.EncodeToBytes();
            }

            byte[][] encKeys = _DeriveKeys(_Keys, _SecretSalt, aad_3, _algAEAD);

            Encrypt0Message enc = new Encrypt0Message(false);

            enc.SetContent(signBody);
            enc.SetExternalData(aad_3);
            enc.AddAttribute(HeaderKeys.Algorithm, _algAEAD, Attributes.DO_NOT_SEND);
            enc.AddAttribute(HeaderKeys.IV, CBORObject.FromObject(encKeys[1]), Attributes.DO_NOT_SEND);
            enc.Encrypt(encKeys[0]);

            msg.Add(enc.EncodeToBytes());

            byte[] msgOut = msg.EncodeToBytes();

            _LastMessageAuthenticator = ConcatenateAndHash(new byte[2][] { _LastMessageAuthenticator, msgOut }, _MessageDigest);

            return(msgOut);
        }
예제 #13
0
        private static CBORObject readList(Stream stream)
        {
            CBORObject obj = CBORObject.NewArray();

            while (true)
            {
                CBORObject o = readObject(stream, true);
                if (o == null)
                {
                    break; // 'e' was read
                }
                obj.Add(o);
            }
            return(obj);
        }
예제 #14
0
        public CBORObject EncodeToCBORObject(CoralDictionary dictionary = null)
        {
            CBORObject root = CBORObject.NewArray();

            if (dictionary == null)
            {
                dictionary = CoralDictionary.Default;
            }

            foreach (CoralItem item in _items)
            {
                root.Add(item.EncodeToCBORObject(dictionary));
            }

            return(root);
        }
예제 #15
0
        /// <summary>
        /// Generate a new CBOR Object based on the message.
        /// Doing this will force cryptographic operations to be created.
        /// </summary>
        /// <returns></returns>
        public CBORObject EncodeToCBORObject()
        {
            CBORObject obj  = CBORObject.NewArray();
            CBORObject obj3 = Encode();

            for (int i = 0; i < obj3.Count; i++)
            {
                obj.Add(obj3[i]);
            }

            if (m_emitTag)
            {
                return(CBORObject.FromObjectAndTag(obj, (int)m_tag));
            }
            return(obj);
        }
예제 #16
0
        private static void SerializeResource(IResource resource, CBORObject cbor, Dictionary <string, CBORObject> dictionary)
        {
            CBORObject obj = CBORObject.NewMap();

            if (dictionary == null)
            {
                obj.Add("href", resource.Path + resource.Name);
            }
            else
            {
                obj.Add(1, resource.Path + resource.Name);
            }
            SerializeAttributes(resource.Attributes, obj, dictionary);

            cbor.Add(obj);
        }
예제 #17
0
        public CBORObject EncodeToCBORObject(Cori coriBase, CoralDictionary dictionary = null)
        {
            CBORObject root = CBORObject.NewArray();

            if (dictionary == null)
            {
                dictionary = CoralDictionary.Default;
            }

            foreach (CoralItem item in _items)
            {
                root.Add(item.EncodeToCBORObject(coriBase, dictionary));
                if (item is CoralBaseDirective d)
                {
                    coriBase = d.BaseValue.ResolveTo(coriBase);
                }
            }

            return(root);
        }
예제 #18
0
        /// <summary>Fill byte array with random values.</summary>
        /// <param name="bytes">Array to receive bytes.</param>
        /// <param name="start">Index to start filling at.</param>
        /// <param name="len">Length of segment to fill.</param>
        public override void NextBytes(byte[] bytes, int start, int len)
        {
            if (m_iRngData + len > m_rgbRngData.Length)
            {
                if (m_prng == null)
                {
                    m_prng = new SecureRandom();
                }

                int cbOld = m_rgbRngData.Length;
                Array.Resize(ref m_rgbRngData, m_iRngData + len);
                m_prng.NextBytes(m_rgbRngData, cbOld, m_rgbRngData.Length - cbOld);
                m_fDirty = true;
            }

            Array.Copy(m_rgbRngData, m_iRngData, bytes, start, len);

            byte[] x = new byte[len];
            Array.Copy(m_rgbRngData, m_iRngData, x, 0, len);
            objNew.Add(CBORObject.FromObject(Program.ToHex(x)));

            m_iRngData += len;
        }
예제 #19
0
        public void SetClaim(string claim, CBORObject value)
        {
            switch (claim)
            {
            case "iss":
            case "sub":
            case "aud":
                if (value.Type != CBORType.TextString)
                {
                    throw new JwtException("Claim value type is incorrect for the claim");
                }
                break;

            case "exp":
            case "nbf":
            case "iat":
                if (value.Type != CBORType.Integer)
                {
                    throw new JwtException("Claim value type is incorrect for the claim");
                }
                break;

            case "jti":
                if (value.Type != CBORType.TextString)
                {
                    throw new JwtException("Claim value type is incorrect for the claim");
                }
                break;

            default:
                //  We don't know how to check this
                break;
            }

            _claims.Add(claim, value);
        }
예제 #20
0
        protected void ProcessCounterSignatures()
        {
            if (CounterSignerList.Count != 0)
            {
                if (CounterSignerList.Count == 1)
                {
                    AddAttribute(HeaderKeys.CounterSignature, CounterSignerList[0].EncodeToCBORObject(ProtectedBytes, rgbSignature), UNPROTECTED);
                }
                else
                {
                    CBORObject list = CBORObject.NewArray();
                    foreach (CounterSignature sig in CounterSignerList)
                    {
                        list.Add(sig.EncodeToCBORObject(ProtectedBytes, rgbSignature));
                    }
                    AddAttribute(HeaderKeys.CounterSignature, list, UNPROTECTED);
                }
            }

            if (CounterSigner1 != null)
            {
                AddAttribute(HeaderKeys.CounterSignature0, CounterSigner1.EncodeToCBORObject(ProtectedBytes, rgbSignature), UNPROTECTED);
            }
        }
예제 #21
0
        /// <inheritdoc />
        public override void ReceiveRequest(INextLayer nextLayer, Exchange exchange, Request request)
        {
            if (!request.HasOption(OptionType.Oscoap))
            {
                base.ReceiveRequest(nextLayer, exchange, request);
                return;
            }
            Response response;

            try {
                Option op = request.GetFirstOption(OptionType.Oscoap);
                request.RemoveOptions(OptionType.Oscoap);

                _Log.Info(m => m("Incoming Request: {0}", Util.Utils.ToString(request)));

                Encrypt0Message msg = Uncompress(op.RawValue);
                if (msg == null)
                {
                    //  Only bother to reply to CON messages
                    if (request.Type == MessageType.CON)
                    {
                        response = new Response(StatusCode.BadOption)
                        {
                            PayloadString = "Unable to decompress"
                        };
                        exchange.SendResponse(response);
                    }
                    return;
                }
                msg.SetEncryptedContent(request.Payload);

                List <SecurityContext> contexts = new List <SecurityContext>();
                SecurityContext        ctx      = null;
                CBORObject             kid;

                //  We may know the context because it is a follow up on a conversation -
                //  In which case we can just use the same one.
                //  M00BUG - Multicast problem of recipient ID?

                CBORObject gid = null;
                if (exchange.OscoapContext != null)
                {
                    contexts.Add(exchange.OscoapContext);
                    if (exchange.OscoapContext.GroupId != null)
                    {
                        gid = CBORObject.FromObject(exchange.OscoapContext.GroupId);
                    }
                    kid = CBORObject.FromObject(exchange.OscoapSenderId);
                }
                else
                {
                    gid = msg.FindAttribute(CBORObject.FromObject("gid"));
                    kid = msg.FindAttribute(HeaderKeys.KeyId);

                    if (kid == null)
                    {
                        exchange.SendResponse(new Response(StatusCode.BadRequest));
                        return;
                    }

                    if (gid != null)
                    {
                        contexts = SecurityContextSet.AllContexts.FindByGroupId(gid.GetByteString());
                    }
                    else
                    {
                        contexts = SecurityContextSet.AllContexts.FindByKid(kid.GetByteString());
                    }

                    if (contexts.Count == 0)
                    {
                        response = new Response(StatusCode.Unauthorized)
                        {
                            PayloadString = "No Context Found - 1"
                        };
                        exchange.SendResponse(response);
                        return; // Ignore messages that have no known security context.
                    }
                }

                byte[] partialIV = msg.FindAttribute(HeaderKeys.PartialIV).GetByteString();

                //  Build AAD
                CBORObject aad = CBORObject.NewArray();
                aad.Add(CBORObject.FromObject(1));    // M00BUG
                aad.Add(CBORObject.NewArray());       // Array place holder
                aad[1].Add(CBORObject.FromObject(0)); // Place holder for algorithm
                aad.Add(CBORObject.FromObject(kid));
                aad.Add(CBORObject.FromObject(partialIV));
                aad.Add(CBORObject.FromObject(new byte[0])); // encoded I options
                if (gid != null)
                {
                    aad.Add(gid);
                }

                byte[] payload = null;

                byte[] seqNoArray = new byte[8];
                Array.Copy(partialIV, 0, seqNoArray, 8 - partialIV.Length, partialIV.Length);
                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(seqNoArray);
                }
                Int64 seqNo = BitConverter.ToInt64(seqNoArray, 0);

                String responseString = "General decrypt failure";

                foreach (SecurityContext context in contexts)
                {
                    SecurityContext.EntityContext recip = context.Recipient;
                    if (recip == null)
                    {
                        if (kid == null)
                        {
                            continue;
                        }
                        recip = context.Recipients[kid.GetByteString()];
                        if (recip == null)
                        {
                            continue;
                        }
                    }

                    if (_replayWindow && recip.ReplayWindow.HitTest(seqNo))
                    {
                        _Log.Info(m => m("Hit test on {0} failed", seqNo));
                        responseString = "Hit test - duplicate";
                        continue;
                    }

                    aad[1][0] = recip.Algorithm;

                    if (_Log.IsInfoEnabled)
                    {
                        _Log.Info("AAD = " + BitConverter.ToString(aad.EncodeToBytes()));
                        _Log.Info("IV = " + BitConverter.ToString(recip.GetIV(partialIV).GetByteString()));
                        _Log.Info("Key = " + BitConverter.ToString(recip.Key));
                    }


                    msg.SetExternalData(aad.EncodeToBytes());

                    msg.AddAttribute(HeaderKeys.Algorithm, recip.Algorithm, Attributes.DO_NOT_SEND);
                    msg.AddAttribute(HeaderKeys.IV, recip.GetIV(partialIV), Attributes.DO_NOT_SEND);

                    try {
                        ctx     = context;
                        payload = msg.Decrypt(recip.Key);
                        recip.ReplayWindow.SetHit(seqNo);
                    }
                    catch (Exception e) {
                        if (_Log.IsInfoEnabled)
                        {
                            _Log.Info("--- ", e);
                        }
                        ctx = null;
                    }

                    if (ctx != null)
                    {
                        break;
                    }
                }

                if (ctx == null)
                {
                    if (request.Type == MessageType.CON)
                    {
                        response = new Response(StatusCode.BadRequest)
                        {
                            PayloadString = responseString
                        };
                        exchange.SendResponse(response);
                    }
                    return;
                }

                exchange.OscoapContext        = ctx; // So we know it on the way back.
                request.OscoapContext         = ctx;
                exchange.OscoapSequenceNumber = partialIV;
                exchange.OscoapSenderId       = kid.GetByteString();

                byte[] newRequestData = new byte[payload.Length + _FixedHeader.Length - 1];
                Array.Copy(_FixedHeader, newRequestData, _FixedHeader.Length);
                Array.Copy(payload, 1, newRequestData, _FixedHeader.Length, payload.Length - 1);
                newRequestData[1] = payload[0];

                Codec.IMessageDecoder me = Spec.NewMessageDecoder(newRequestData);
                Request newRequest       = me.DecodeRequest();

                //  Update headers is a pain

                RestoreOptions(request, newRequest);
                request.Method = newRequest.Method;

                if (_Log.IsInfoEnabled)
                {
                    // log.Info(String.Format("Secure message post = " + Util.Utils.ToString(request)));
                }

                //  We may want a new exchange at this point if it relates to a new message for blockwise.

                if (request.HasOption(OptionType.Block2))
                {
                    Exchange.KeyUri keyUri = new Exchange.KeyUri(request.URI, null, request.Source);
                    BlockHolder     block;
                    _ongoingExchanges.TryGetValue(keyUri, out block);

                    if (block != null)
                    {
                        block.RestoreTo(exchange);
                    }
                }

                request.Payload = newRequest.Payload;
            }
            catch (Exception e) {
                _Log.Error("OSCOAP Layer: reject message because ", e);
                exchange.OscoapContext = null;

                if (request.Type == MessageType.CON)
                {
                    response = new Response(StatusCode.Unauthorized)
                    {
                        Payload = Encoding.UTF8.GetBytes("Error is " + e.Message)
                    };
                    exchange.SendResponse(response);
                }
                //  Ignore messages that we cannot decrypt.
                return;
            }

            base.ReceiveRequest(nextLayer, exchange, request);
        }
예제 #22
0
#pragma warning restore 618
    private static void FromArrayRecursive(
  Array arr,
  int[] index,
  int dimension,
  CBORObject obj) {
      int dimLength = arr.GetLength(dimension);
      int rank = index.Length;
      for (var i = 0; i < dimLength; ++i) {
        if (dimension + 1 == rank) {
          index[dimension] = i;
          obj.Add(CBORObject.FromObject(arr.GetValue(index)));
        } else {
          CBORObject child = CBORObject.NewArray();
          for (int j = dimension + 1; j < dimLength; ++j) {
            index[j] = 0;
          }
          FromArrayRecursive(arr, index, dimension + 1, child);
          obj.Add(child);
        }
      }
    }
예제 #23
0
        /// <inheritdoc />
        protected override CBORObject InternalEncodeToJSON(bool fCompact)
        {
            CBORObject obj = CBORObject.NewMap();

            if (UnprotectedMap.Count > 0)
            {
                obj.Add("unprotected", UnprotectedMap);                           // Add unprotected attributes
            }
            //  Look at the world of base64 encoded bodies.
            //   If any signer has the b64 false, then all of them need to.
            //   Then change our body if needed

            int  b64Found = 0;
            bool b64Value = true;

            foreach (Signer key in SignerList)
            {
                CBORObject attr = key.FindAttribute(CBORObject.FromObject("b64"), PROTECTED);
                if (attr != null)
                {
                    if (b64Found == 0)
                    {
                        b64Value = attr.AsBoolean();
                    }
                    else if (b64Value != attr.AsBoolean())
                    {
                        throw new JoseException("Not all signers using the same value for b64");
                    }
                    b64Found += 1;
                }
            }

            if (b64Value)
            {
                obj.Add("payload", base64urlencode(payload));
            }
            else
            {
                if (b64Found != SignerList.Count)
                {
                    throw new JoseException("Not all signers using the same value for b64");
                }
                obj.Add("payload", Encoding.UTF8.GetString(payload));
            }

            if (SignerList.Count > 0)
            {
                CBORObject signers = CBORObject.NewArray();

                foreach (Signer key in SignerList)
                {
                    signers.Add(key.EncodeToJSON(payload));
                }

                if (fCompact)
                {
                    if (SignerList.Count > 1)
                    {
                        throw new JoseException("Compact format must be for single signer");
                    }

                    if (signers[0].ContainsKey("protected"))
                    {
                        obj.Add("protected", signers[0]["protected"]);
                    }
                    obj.Add("signature", signers[0]["signature"]);
                }
                else
                {
                    obj.Add("signatures", signers);
                }
            }
            else
            {
                throw new JoseException("Must have some signers");
            }

            return(obj);
        }
예제 #24
0
파일: Key.cs 프로젝트: gunnarif/COSE-csharp
 public void Add(string key, string value)
 {
     _json.Add(key, CBORObject.FromObject(value));
 }
예제 #25
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);
        }
예제 #26
0
        /// <inheritdoc />
        public override void SendRequest(INextLayer nextLayer, Exchange exchange, Request request)
        {
            if ((request.OscoapContext != null) || (exchange.OscoapContext != null))
            {
                SecurityContext ctx = exchange.OscoapContext;
                if (request.OscoapContext != null)
                {
                    ctx = request.OscoapContext;
                    exchange.OscoapContext = ctx;
                }

                Codec.IMessageEncoder me = Spec.NewMessageEncoder();
                Request encryptedRequest = new Request(request.Method);

                if (request.Payload != null)
                {
                    encryptedRequest.Payload = request.Payload;
                }

                MoveRequestHeaders(request, encryptedRequest);

                _Log.Info(m => m("New inner response message\n{0}", encryptedRequest.ToString()));

                ctx.Sender.IncrementSequenceNumber();

                Encrypt0Message enc       = new Encrypt0Message(false);
                byte[]          msg       = me.Encode(encryptedRequest);
                int             tokenSize = msg[0] & 0xf;
                byte[]          msg2      = new byte[msg.Length - (3 + tokenSize)];
                Array.Copy(msg, 4 + tokenSize, msg2, 1, msg2.Length - 1);
                msg2[0] = msg[1];
                enc.SetContent(msg2);

                // Build AAD
                CBORObject aad = CBORObject.NewArray();
                aad.Add(CBORObject.FromObject(1)); // version
                aad.Add(CBORObject.NewArray());
                aad[1].Add(CBORObject.FromObject(ctx.Sender.Algorithm));
                aad.Add(CBORObject.FromObject(ctx.Sender.Id));
                aad.Add(CBORObject.FromObject(ctx.Sender.PartialIV));
                aad.Add(CBORObject.FromObject(new byte[0]));
                if (ctx.GroupId != null)
                {
                    aad.Add(CBORObject.FromObject(ctx.GroupId));
                }

#if DEBUG
                switch (SecurityContext.FutzError)
                {
                case 1:
                    aad[0] = CBORObject.FromObject(2);
                    break;     // Change version #

                case 2:
                    aad[1] = CBORObject.FromObject(request.Code + 1);
                    break;     // Change request code

                case 3:
                    aad[2] = CBORObject.FromObject(ctx.Sender.Algorithm.AsInt32() + 1);
                    break;     // Change algorithm number
                }
#endif

                _Log.Info(m => m("SendRequest: AAD = {0}", BitConverter.ToString(aad.EncodeToBytes())));

                enc.SetExternalData(aad.EncodeToBytes());
#if DEBUG
                {
                    byte[] fooX = ctx.Sender.PartialIV;
                    if (SecurityContext.FutzError == 8)
                    {
                        fooX[fooX.Length - 1] += 1;
                    }
                    enc.AddAttribute(HeaderKeys.IV, ctx.Sender.GetIV(fooX), Attributes.DO_NOT_SEND);
                }
#else
                enc.AddAttribute(HeaderKeys.IV, ctx.Sender.GetIV(ctx.Sender.PartialIV), Attributes.DO_NOT_SEND);
#endif
                enc.AddAttribute(HeaderKeys.PartialIV, CBORObject.FromObject(ctx.Sender.PartialIV), /* Attributes.PROTECTED */ Attributes.DO_NOT_SEND);
                enc.AddAttribute(HeaderKeys.Algorithm, ctx.Sender.Algorithm, Attributes.DO_NOT_SEND);
                enc.AddAttribute(HeaderKeys.KeyId, CBORObject.FromObject(ctx.Sender.Id), /*Attributes.PROTECTED*/ Attributes.DO_NOT_SEND);
                if (ctx.GroupId != null)
                {
                    enc.AddAttribute(CBORObject.FromObject("gid"), CBORObject.FromObject(ctx.GroupId), Attributes.DO_NOT_SEND);
                }

                if (_Log.IsInfoEnabled)
                {
                    _Log.Info("SendRequest: AAD = " + BitConverter.ToString(aad.EncodeToBytes()));
                    _Log.Info("SendRequest: IV = " + BitConverter.ToString(ctx.Sender.GetIV(ctx.Sender.PartialIV).GetByteString()));
                    _Log.Info("SendRequest: Key = " + BitConverter.ToString(ctx.Sender.Key));
                }

                enc.Encrypt(ctx.Sender.Key);

                if (ctx.Sender.SigningKey != null)
                {
                    CounterSignature sig = new CounterSignature(ctx.Sender.SigningKey);
                    sig.AddAttribute(HeaderKeys.Algorithm, ctx.Sender.SigningKey[CoseKeyKeys.Algorithm], Attributes.DO_NOT_SEND);
                    sig.SetObject(enc);
                    CBORObject aad2 = ctx.Sender.SigningKey[CoseKeyKeys.Algorithm];
                    sig.SetExternalData(aad2.EncodeToBytes());
                    CBORObject signatureBytes = sig.EncodeToCBORObject();
                    enc.AddAttribute(HeaderKeys.CounterSignature, signatureBytes, Attributes.DO_NOT_SEND);
                }

                byte[] optionValue = DoCompression(enc);

                OscoapOption o = new OscoapOption();
                o.Set(optionValue);
                request.AddOption(o);
                request.Payload = enc.GetEncryptedContent();

                if (request.HasOption(OptionType.Observe))
                {
                    request.Method = Method.FETCH;
                }
                else
                {
                    request.Method = Method.POST;
                }
            }
            base.SendRequest(nextLayer, exchange, request);
        }
예제 #27
0
        public override void SendResponse(INextLayer nextLayer, Exchange exchange, Response response)
        {
            if (exchange.OscoapContext != null)
            {
                SecurityContext ctx = exchange.OscoapContext;

                Codec.IMessageEncoder me   = Spec.NewMessageEncoder();
                Response encryptedResponse = new Response((StatusCode)response.Code);

                if (response.Payload != null)
                {
                    encryptedResponse.Payload = response.Payload;
                }

                MoveResponseHeaders(response, encryptedResponse);

                if (_Log.IsInfoEnabled)
                {
                    _Log.Info("SendResponse: New inner response message");
                    _Log.Info(encryptedResponse.ToString());
                }

                //  Build AAD
                CBORObject aad = CBORObject.NewArray();
                aad.Add(1);
                aad.Add(CBORObject.NewArray());
                aad[1].Add(ctx.Sender.Algorithm);
                aad.Add(exchange.OscoapSenderId);
                aad.Add(exchange.OscoapSequenceNumber);
                aad.Add(CBORObject.FromObject(new byte[0])); // Options
                if (ctx.GroupId != null)
                {
                    aad.Add(ctx.GroupId);
                }

                if (_Log.IsInfoEnabled)
                {
                    _Log.Info("SendResponse: AAD = " + BitConverter.ToString(aad.EncodeToBytes()));
                }

                Encrypt0Message enc       = new Encrypt0Message(false);
                byte[]          msg       = me.Encode(encryptedResponse);
                int             tokenSize = msg[0] & 0xf;
                byte[]          msg2      = new byte[msg.Length - (3 + tokenSize)];
                Array.Copy(msg, 4 + tokenSize, msg2, 1, msg2.Length - 1);
                msg2[0] = msg[1];
                enc.SetContent(msg2);
                enc.SetExternalData(aad.EncodeToBytes());

                if (response.HasOption(OptionType.Observe) || ctx.GroupId != null)
                {
                    enc.AddAttribute(HeaderKeys.PartialIV, CBORObject.FromObject(ctx.Sender.PartialIV), Attributes.UNPROTECTED);
                    enc.AddAttribute(HeaderKeys.IV, ctx.Sender.GetIV(ctx.Sender.PartialIV), Attributes.DO_NOT_SEND);
                    ctx.Sender.IncrementSequenceNumber();
                    if (ctx.GroupId != null)
                    {
                        enc.AddAttribute(HeaderKeys.KeyId, CBORObject.FromObject(ctx.Sender.Id), Attributes.UNPROTECTED);
                    }
                }
                else
                {
                    CBORObject iv = ctx.Recipient.GetIV(exchange.OscoapSequenceNumber);

                    enc.AddAttribute(HeaderKeys.IV, iv, Attributes.DO_NOT_SEND);
                }

                _Log.Info(m => m($"SendResponse: IV = {BitConverter.ToString(enc.FindAttribute(HeaderKeys.IV, Attributes.DO_NOT_SEND).GetByteString())}"));
                _Log.Info(m => m($"SendResponse: Key = {BitConverter.ToString(ctx.Sender.Key)}"));

                enc.AddAttribute(HeaderKeys.Algorithm, ctx.Sender.Algorithm, Attributes.DO_NOT_SEND);
                enc.Encrypt(ctx.Sender.Key);

                byte[] finalBody = DoCompression(enc);

                OscoapOption o = new OscoapOption(OptionType.Oscoap);
                o.Set(finalBody);
                response.AddOption(o);
                response.StatusCode = StatusCode.Content;
                response.Payload    = enc.GetEncryptedContent();

                //  Need to be able to retrieve this again undersome cirumstances.

                if (encryptedResponse.HasOption(OptionType.Block2))
                {
                    Request         request = exchange.CurrentRequest;
                    Exchange.KeyUri keyUri  = new Exchange.KeyUri(request.URI, null, response.Destination);

                    //  Observe notification only send the first block, hence do not store them as ongoing
                    if (exchange.OSCOAP_ResponseBlockStatus != null && !encryptedResponse.HasOption(OptionType.Observe))
                    {
                        //  Remember ongoing blockwise GET requests
                        BlockHolder blockInfo = new BlockHolder(exchange);
                        if (Util.Utils.Put(_ongoingExchanges, keyUri, blockInfo) == null)
                        {
                            if (_Log.IsInfoEnabled)
                            {
                                _Log.Info("Ongoing Block2 started late, storing " + keyUri + " for " + request);
                            }
                        }
                        else
                        {
                            if (_Log.IsInfoEnabled)
                            {
                                _Log.Info("Ongoing Block2 continued, storing " + keyUri + " for " + request);
                            }
                        }
                    }
                    else
                    {
                        if (_Log.IsInfoEnabled)
                        {
                            _Log.Info("Ongoing Block2 completed, cleaning up " + keyUri + " for " + request);
                        }
                        BlockHolder exc;
                        _ongoingExchanges.TryRemove(keyUri, out exc);
                    }
                }
            }

            base.SendResponse(nextLayer, exchange, response);
        }
예제 #28
0
        public override void ReceiveResponse(INextLayer nextLayer, Exchange exchange, Response response)
        {
            if (response.HasOption(OptionType.Oscoap))
            {
                Option op = response.GetFirstOption(OptionType.Oscoap);

                if (exchange.OscoapContext == null)
                {
                    return;
                }

                SecurityContext ctx = exchange.OscoapContext;

                bool fServerIv = true;

                Encrypt0Message msg = Uncompress(op.RawValue);
                if (msg == null)
                {
                    return;
                }
                msg.SetEncryptedContent(response.Payload);

                SecurityContext.EntityContext recip = ctx.Recipient;
                if (recip == null)
                {
                    if (ctx.GroupId == null)
                    {
                        //  This is not currently a valid state to be in
                        return;
                    }
                    CBORObject kid = msg.FindAttribute(HeaderKeys.KeyId);
                    if (kid == null)
                    {
                        //  this is not currently a valid state to be in
                        return;
                    }
                    recip = ctx.Recipients[kid.GetByteString()];
                    if (recip == null)
                    {
                        // M00TODO - deal with asking the user for a recipient structure at this point.
                        return;
                    }
                }

                if (msg.FindAttribute(HeaderKeys.PartialIV) == null)
                {
                    msg.AddAttribute(HeaderKeys.PartialIV, CBORObject.FromObject(ctx.Sender.PartialIV), Attributes.DO_NOT_SEND);
                    fServerIv = false;
                }


                byte[] partialIV  = msg.FindAttribute(HeaderKeys.PartialIV).GetByteString();
                byte[] seqNoArray = new byte[8];
                Array.Copy(partialIV, 0, seqNoArray, 8 - partialIV.Length, partialIV.Length);
                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(seqNoArray);
                }
                Int64 seqNo = BitConverter.ToInt64(seqNoArray, 0);

                if (fServerIv)
                {
                    if (_replayWindow && recip.ReplayWindow.HitTest(seqNo))
                    {
                        return;
                    }
                }

                msg.AddAttribute(HeaderKeys.Algorithm, recip.Algorithm, Attributes.DO_NOT_SEND);

                CBORObject fullIV;
                if (fServerIv)
                {
                    fullIV = recip.GetIV(partialIV);
                }
                else
                {
                    fullIV = ctx.Sender.GetIV(partialIV);
                }
                msg.AddAttribute(HeaderKeys.IV, fullIV, Attributes.DO_NOT_SEND);

                //  build aad
                CBORObject aad = CBORObject.NewArray();
                aad.Add(1);
                aad.Add(CBORObject.NewArray());
                aad[1].Add(recip.Algorithm);
                aad.Add(ctx.Sender.Id);
                aad.Add(ctx.Sender.PartialIV);
                aad.Add(CBORObject.FromObject(new byte[0])); // OPTIONS
                if (ctx.GroupId != null)
                {
                    aad.Add(ctx.GroupId);
                }

                msg.SetExternalData(aad.EncodeToBytes());

                _Log.Info(m => m($"fServerIv = {fServerIv}"));
                _Log.Info(m => m("ReceiveResponse: AAD = " + BitConverter.ToString(aad.EncodeToBytes())));
                _Log.Info(m => m($"ReceiveResponse: IV = {BitConverter.ToString(fullIV.GetByteString())}"));
                _Log.Info(m => m($"ReceiveResponse: Key = {BitConverter.ToString(recip.Key)}"));

                byte[] payload = msg.Decrypt(recip.Key);

                recip.ReplayWindow.SetHit(seqNo);

                byte[] rgb = new byte[payload.Length + _FixedHeader.Length - 1];
                Array.Copy(_FixedHeader, rgb, _FixedHeader.Length);
                Array.Copy(payload, 1, rgb, _FixedHeader.Length, payload.Length - 1);
                rgb[1] = payload[0];
                Codec.IMessageDecoder me = Spec.NewMessageDecoder(rgb);
                Response decryptedReq    = me.DecodeResponse();

                response.Payload    = decryptedReq.Payload;
                response.StatusCode = decryptedReq.StatusCode;

                RestoreOptions(response, decryptedReq);
            }
            base.ReceiveResponse(nextLayer, exchange, response);
        }
예제 #29
0
        public override CBORObject Encode()
        {
            CBORObject obj;

            byte[] rgbProtected;

            obj = CBORObject.NewArray();

            if ((objProtected != null) && (objProtected.Count > 0))
            {
                rgbProtected = objProtected.EncodeToBytes();
                obj.Add(rgbProtected);
            }
            else
            {
                rgbProtected = new byte[0];
                obj.Add(rgbProtected);
            }

            if (m_counterSignerList.Count() != 0)
            {
                if (m_counterSignerList.Count() == 1)
                {
                    AddUnprotected(HeaderKeys.CounterSignature, m_counterSignerList[0].EncodeToCBORObject(rgbProtected, rgbContent));
                }
                else
                {
                    foreach (CounterSignature sig in m_counterSignerList)
                    {
                        sig.EncodeToCBORObject(rgbProtected, rgbContent);
                    }
                }
            }

            if ((objUnprotected == null) || (objUnprotected.Count == 0))
            {
                obj.Add(CBORObject.NewMap());
            }
            else
            {
                obj.Add(objUnprotected);  // Add unprotected attributes
            }
            obj.Add(rgbContent);

            if ((signerList.Count == 1) && !this.m_forceArray)
            {
                CBORObject recipient = signerList[0].EncodeToCBORObject(obj[0].EncodeToBytes(), rgbContent);

                for (int i = 0; i < recipient.Count; i++)
                {
                    obj.Add(recipient[i]);
                }
            }
            else if (signerList.Count > 0)
            {
                CBORObject signers = CBORObject.NewArray();

                foreach (Signer key in signerList)
                {
                    signers.Add(key.EncodeToCBORObject(rgbProtected, rgbContent));
                }
                obj.Add(signers);
            }
            else
            {
                obj.Add(null);      // No recipients - set to null
            }
            return(obj);
        }
예제 #30
0
        private static Encrypt0Message Uncompress(byte[] raw)
        {
            CBORObject map = CBORObject.NewMap();

            if (raw.Length == 0)
            {
                raw = new byte[1];
            }

            //  Decode the wierd body
            //  First byte is of the form 0abcdeee where abcd are flags and eee is the the IV size.
            if (0 != (raw[0] & 0x80))
            {
                return(null);                      // This is not legal
            }
            if (0 != (raw[0] & 0x40))
            {
                return(null);                      // These are not currently supported.
            }
            int iX = 1;

            if (0 != (raw[0] & 0x07))
            {
                byte[] ivX = new byte[raw[0] & 0x7];
                Array.Copy(raw, iX, ivX, 0, ivX.Length);
                map.Add(HeaderKeys.PartialIV, ivX);
                iX += ivX.Length;
            }

            if (0 != (raw[0] & 0x10))
            {
                byte[] gidX = new byte[raw[iX]];
                Array.Copy(raw, iX + 1, gidX, 0, gidX.Length);
                iX += (gidX.Length + 1);
                map.Add(CBORObject.FromObject("gid"), gidX);
            }

            if (0 != (raw[0] & 0x20))
            {
                byte[] counter = new byte[raw[iX]];
                Array.Copy(raw, iX + 1, counter, 0, counter.Length);
                iX += (counter.Length + 1);
                map.Add(HeaderKeys.CounterSignature, counter);
            }

            if (0 != (raw[0] & 0x08))
            {
                byte[] kidX = new byte[raw.Length - iX];
                Array.Copy(raw, iX, kidX, 0, kidX.Length);
                map.Add(HeaderKeys.KeyId, kidX);
            }

            CBORObject msgX = CBORObject.NewArray();

            msgX.Add(new byte[0]);
            msgX.Add(map);
            msgX.Add(CBORObject.Null);

            Encrypt0Message msg = (Encrypt0Message)COSE.Message.DecodeFromBytes(msgX.EncodeToBytes(), Tags.Encrypt0);

            return(msg);
        }
예제 #31
0
        public byte[] CreateMessage2()
        {
            CBORObject msg = CBORObject.NewArray();
            CBORObject obj;

            if (_fSymmetricSecret)
            {
                msg.Add(5);             // Msg Type
            }
            else
            {
                msg.Add(2);
            }

            msg.Add(_SessionId[1]);                 // S_U
            msg.Add(_SessionId[0]);                 // S_V
            msg.Add(_Nonce[0]);                     // N_V
            msg.Add(_Keys[0].PublicKey().AsCBOR()); // E_V
            msg.Add(_algKeyAgree);                  // HKDF_V
            msg.Add(_algAEAD);                      // AEAD_V
            if (!_fSymmetricSecret)
            {
                msg.Add(_algSign);          // SIG_V

                obj = CBORObject.NewArray();
                obj.Add(AlgorithmValuesInt.ECDSA_256);
                obj.Add(AlgorithmValues.EdDSA);
                msg.Add(obj);               // SIGs_V
            }

            if (_algKeyAgree.Equals(COSE.AlgorithmValues.ECDH_SS_HKDF_256))
            {
                _MessageDigest = new Sha256Digest();
            }

            byte[] data2 = msg.EncodeToBytes();
            byte[] aad_2 = ConcatenateAndHash(new byte[2][] { _Messages[0], data2 }, _MessageDigest);   // M00TODO - hash message[0] before passing it in.

            byte[][] useKeys = _DeriveKeys(_Keys, _SecretSalt, aad_2, _algAEAD);
            byte[]   aeadKey = useKeys[0];

            byte[] signResult = new byte[0];
            if (!_fSymmetricSecret)
            {
                Sign1Message sign1 = new Sign1Message(false, false);
                sign1.SetContent(aad_2);
                sign1.AddAttribute(HeaderKeys.KeyId, _SigningKey[CoseKeyKeys.KeyIdentifier], Attributes.UNPROTECTED);
                sign1.AddAttribute(HeaderKeys.Algorithm, _algSign, Attributes.DO_NOT_SEND);

                sign1.Sign(_SigningKey);
                signResult = sign1.EncodeToBytes();
            }

            Encrypt0Message enc0 = new Encrypt0Message(true);

            enc0.AddAttribute(HeaderKeys.Algorithm, _algAEAD, Attributes.DO_NOT_SEND);
            enc0.AddAttribute(HeaderKeys.IV, CBORObject.FromObject(useKeys[1]), Attributes.DO_NOT_SEND);
            enc0.SetExternalData(aad_2);
            CBORObject encContent = CBORObject.NewArray();

            encContent.Add(signResult);
            enc0.SetContent(encContent.EncodeToBytes());

            enc0.Encrypt(aeadKey);
            msg.Add(enc0.EncodeToCBORObject());  // COSE_ENC_2

            _Messages[1] = msg.EncodeToBytes();

            _LastMessageAuthenticator = ConcatenateAndHash(new byte[][] { _Messages[0], _Messages[1] }, _MessageDigest);

            return(_Messages[1]);
        }