/// <summary> /// Given a CBOR tree, decode and return the correct COSE message object. /// Message type can be provided explicitly or inferred from the CBOR tag element. /// If the explicit and inferred elements provide different answers, then it fails. /// </summary> /// <param name="messageObject"></param> /// <param name="defaultTag"></param> /// <returns></returns> public static Message DecodeFromCBOR(CBORObject messageObject, Tags defaultTag = Tags.Unknown) { if (messageObject.Type != CBORType.Array) { throw new CoseException("Message is not a COSE security message."); } if (messageObject.IsTagged) { if (messageObject.GetAllTags().Count() != 1) { throw new CoseException("Malformed message - too many tags"); } if (defaultTag == Tags.Unknown) { defaultTag = (Tags)messageObject.MostOuterTag.ToInt32Checked(); } else if (defaultTag != (Tags)messageObject.MostOuterTag.ToInt32Checked()) { throw new CoseException("Passed in tag does not match actual tag"); } } Message returnObject; switch (defaultTag) { case Tags.Unknown: throw new CoseException("Message was not tagged and no default tagging option given"); case Tags.Signed: SignMessage sig = new SignMessage(); sig.InternalDecodeFromCBORObject(messageObject); returnObject = sig; break; case Tags.Sign1: Sign1Message sig0 = new Sign1Message(); sig0.InternalDecodeFromCBORObject(messageObject); returnObject = sig0; break; case Tags.MAC: MACMessage mac = new MACMessage(); mac.InternalDecodeFromCBORObject(messageObject); returnObject = mac; break; case Tags.MAC0: MAC0Message mac0 = new MAC0Message(); mac0.InternalDecodeFromCBORObject(messageObject); returnObject = mac0; break; case Tags.Encrypt: // It is an encrytion message EncryptMessage enc = new EncryptMessage(); enc.InternalDecodeFromCBORObject(messageObject); returnObject = enc; break; case Tags.Encrypt0: Encrypt0Message enc0 = new Encrypt0Message(); enc0.InternalDecodeFromCBORObject(messageObject); returnObject = enc0; break; default: throw new CoseException("Message is not recognized as a COSE security message."); } // Check for counter signatures CBORObject csig = returnObject.FindAttribute(HeaderKeys.CounterSignature, UNPROTECTED); if (csig != null) { if (csig.Type != CBORType.Array || csig.Count == 0) { throw new CoseException("Invalid counter signature attribute"); } if (csig[0].Type == CBORType.Array) { foreach (CBORObject cbor in csig.Values) { if (cbor.Type != CBORType.Array) { throw new CoseException("Invalid Counter signature attribute"); } CounterSignature cs = new CounterSignature(cbor); cs.SetObject(returnObject); returnObject.CounterSignerList.Add(cs); } } else { CounterSignature cs = new CounterSignature(csig); cs.SetObject(returnObject); returnObject.CounterSignerList.Add(cs); } } csig = returnObject.FindAttribute(HeaderKeys.CounterSignature0, UNPROTECTED); if (csig != null) { if (csig.Type != CBORType.ByteString) { throw new CoseException("Invalid CounterSignature0 attribute"); } CounterSignature1 cs = new CounterSignature1(csig.GetByteString()); cs.SetObject(returnObject); returnObject.CounterSigner1 = cs; } return(returnObject); }