/** * Constructor that accepts the binary representation of a signed COSE_Sign1 object. * * @param data * the binary representation of the COSE_Sign1 object * @throws CBORException * for invalid data */ public CoseSign1_Object(byte[] data) { CBORObject message = CBORObject.DecodeFromBytes(data); if (message.Type != CBORType.Array) { throw new CBORException("Supplied message is not a valid COSE security object"); } // If the message is tagged, it must have the message tag for a COSE_Sign1 message. // if (message.IsTagged) { if (message.GetAllTags().Length != 1) { throw new CBORException("Invalid object - too many tags"); } if (MessageTag != message.MostInnerTag.ToInt32Unchecked()) { throw new CBORException(String.Format( "Invalid COSE_Sign1 structure - Expected {0} tag - but was {1}", MessageTag, message.MostInnerTag.ToInt32Unchecked())); } } if (message.Count != 4) { throw new CBORException(String.Format( "Invalid COSE_Sign1 structure - Expected an array of 4 items - but array has {0} items", message.Count)); } if (message[0].Type == CBORType.ByteString) { ProtectedAttributesEncoding = message[0].GetByteString(); if (message[0].GetByteString().Length == 0) { ProtectedAttributes = CBORObject.NewMap(); } else { ProtectedAttributes = CBORObject.DecodeFromBytes(ProtectedAttributesEncoding); if (this.ProtectedAttributes.Count == 0) { this.ProtectedAttributesEncoding = new byte[0]; } } } else { throw new CBORException(String.Format("Invalid COSE_Sign1 structure - " + "Expected item at position 1/4 to be a bstr which is the encoding of the protected attributes, but was {0}", message[0].Type)); } if (message[1].Type == CBORType.Map) { UnprotectedAttributes = message[1]; } else { throw new CBORException(String.Format( "Invalid COSE_Sign1 structure - Expected item at position 2/4 to be a Map for unprotected attributes, but was {0}", message[1].Type)); } if (message[2].Type == CBORType.ByteString) { Content = message[2].GetByteString(); } else if (!message[2].IsNull) { throw new CBORException(String.Format( "Invalid COSE_Sign1 structure - Expected item at position 3/4 to be a bstr holding the payload, but was {0}", message[2].Type)); } if (message[3].Type == CBORType.ByteString) { Signature = message[3].GetByteString(); } else { throw new CBORException(String.Format( "Invalid COSE_Sign1 structure - Expected item at position 4/4 to be a bstr holding the signature, but was {0}", message[3].Type)); } }
private static CBORObject FromObjectAndInnerTags( object objectValue, CBORObject objectWithTags) { CBORObject newObject = CBORObject.FromObject(objectValue); if (!objectWithTags.IsTagged) { return newObject; } objectWithTags = objectWithTags.UntagOne(); if (!objectWithTags.IsTagged) { return newObject; } EInteger[] tags = objectWithTags.GetAllTags(); for (int i = tags.Length - 1; i >= 0; --i) { newObject = CBORObject.FromObjectAndTag(newObject, tags[i]); } return newObject; }
/// <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); }