![JAR search and dependency download from the Maven repository](/logo.png)
COSE.Message Maven / Gradle / Ivy
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package COSE;
import com.upokecenter.cbor.CBORObject;
import com.upokecenter.cbor.CBORType;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
/**
* The Message class provides a common class that all of the COSE message classes
* inherit from. It provides the function used for decoding all of the known
* messages.
*
* @author jimsch
*/
public abstract class Message extends Attribute {
/**
* Is the tag identifying the message emitted?
*/
protected boolean emitTag = true;
/**
* Is the content emitted as part of the message?
*/
protected boolean emitContent = true;
/**
* What message tag identifies this message?
*/
protected MessageTag messageTag = MessageTag.Unknown;
/**
* What is the plain text content of the message.
*/
protected byte[] rgbContent = null;
/**
* Decode a COSE message object. This function assumes that the message
* has a leading CBOR tag to identify the message type. If this is not
* true then use {#link DecodeFromBytes(byte[], MessageTag)}.
*
* @param rgbData byte stream to be decoded
* @return the decoded message object
* @throws CoseException on a decode failure
*/
public static Message DecodeFromBytes(byte[] rgbData) throws CoseException {
return DecodeFromBytes(rgbData, MessageTag.Unknown);
}
/**
* Decode a COSE message object. Use a value of {@code MessageTag.Unknown}
* to decode a generic structure with tagging. Use a specific value if
* the tagging is absent or if a known structure is passed in.
*
* @param rgbData byte stream to be decoded
* @param defaultTag assumed message type to be decoded
* @return the decoded message object
* @throws CoseException on a decode failure.
*/
public static Message DecodeFromBytes(byte[] rgbData, MessageTag defaultTag) throws CoseException {
CBORObject messageObject = CBORObject.DecodeFromBytes(rgbData);
if (messageObject.getType() != CBORType.Array) throw new CoseException("Message is not a COSE security Message");
if (messageObject.isTagged()) {
if (messageObject.GetAllTags().length != 1) throw new CoseException("Malformed message - too many tags");
if (defaultTag == MessageTag.Unknown) {
defaultTag = MessageTag.FromInt(messageObject.getMostInnerTag().ToInt32Unchecked());
}
else if (defaultTag != MessageTag.FromInt(messageObject.getMostInnerTag().ToInt32Unchecked())) {
throw new CoseException("Passed in tag does not match actual tag");
}
}
Message msg;
switch (defaultTag) {
case Unknown: // Unknown
throw new CoseException("Message was not tagged and no default tagging option given");
case Encrypt:
msg = new EncryptMessage();
break;
case Encrypt0:
msg = new Encrypt0Message();
break;
case MAC:
msg = new MACMessage();
break;
case MAC0:
msg = new MAC0Message();
break;
case Sign1:
msg = new Sign1Message();
break;
case Sign:
msg = new SignMessage();
break;
default:
throw new CoseException("Message is not recognized as a COSE security Object");
}
msg.DecodeFromCBORObject(messageObject);
CBORObject countersignature = msg.findAttribute(HeaderKeys.CounterSignature, UNPROTECTED);
if (countersignature != null) {
if ((countersignature.getType() != CBORType.Array) ||
(countersignature.getValues().isEmpty())) {
throw new CoseException("Invalid countersignature attribute");
}
if (countersignature.get(0).getType() == CBORType.Array) {
for (CBORObject obj : countersignature.getValues()) {
if (obj.getType() != CBORType.Array) {
throw new CoseException("Invalid countersignature attribute");
}
CounterSign cs = new CounterSign(obj);
cs.setObject(msg);
msg.addCountersignature(cs);
}
}
else {
CounterSign cs = new CounterSign(countersignature);
cs.setObject(msg);
msg.addCountersignature(cs);
}
}
countersignature = msg.findAttribute(HeaderKeys.CounterSignature0, UNPROTECTED);
if (countersignature != null) {
if (countersignature.getType() != CBORType.ByteString) {
throw new CoseException("Invalid Countersignature0 attribute");
}
CounterSign1 cs = new CounterSign1(countersignature.GetByteString());
cs.setObject(msg);
msg.counterSign1 = cs;
}
return msg;
}
/**
* Encode the message to a byte array. This function will force cryptographic operations to be executed as needed.
*
* @return byte encoded object
* @throws CoseException Internal COSE Exception
*/
public byte[] EncodeToBytes() throws CoseException {
return EncodeToCBORObject().EncodeToBytes();
}
/**
* Given a CBOR tree, parse the message. This is an abstract function that is implemented for each different supported COSE message.
*
* @param messageObject CBORObject to be converted to a message.
* @throws CoseException Internal COSE Exception
*/
protected abstract void DecodeFromCBORObject(CBORObject messageObject) throws CoseException;
/**
* Encode the COSE message object to a CBORObject tree. This function call will force cryptographic operations to be executed as needed.
* This is an internal function, as such it does not add the tag on the front and is implemented on a per message object.
*
* @return CBORObject representing the message.
* @throws CoseException Internal COSE Exception
*/
protected abstract CBORObject EncodeCBORObject() throws CoseException;
/**
* Encode the COSE message object to a CBORObject tree. This function call will force cryptographic operations to be executed as needed.
*
* @return CBORObject representing the message.
* @throws CoseException Internal COSE Exception
*/
public CBORObject EncodeToCBORObject() throws CoseException {
CBORObject obj;
obj = EncodeCBORObject();
if (emitTag) {
obj = CBORObject.FromObjectAndTag(obj, messageTag.value);
}
return obj;
}
/**
* Return the content bytes of the message
*
* @return bytes of the content
*/
public byte[] GetContent() {
return rgbContent;
}
/**
* Does the message current have content?
*
* @return true if it has content
*/
public boolean HasContent() {
return rgbContent != null;
}
/**
* Set the content bytes of the message. If the message was transmitted with
* detached content, this must be called before doing cryptographic processing on the message.
*
* @param rgbData bytes to set as the content
*/
public void SetContent(byte[] rgbData) {
rgbContent = rgbData;
}
/**
* Set the content bytes as a text string. The string will be encoded using UTF8 into a byte string.
*
* @param strData string to set as the content
*/
public void SetContent(String strData) {
rgbContent = strData.getBytes(StandardCharsets.UTF_8);
}
List counterSignList = new ArrayList();
CounterSign1 counterSign1;
public void addCountersignature(CounterSign countersignature)
{
counterSignList.add(countersignature);
}
public List getCountersignerList() {
return counterSignList;
}
public CounterSign1 getCountersign1() {
return counterSign1;
}
public void setCountersign1(CounterSign1 value) {
counterSign1 = value;
}
protected void ProcessCounterSignatures() throws CoseException {
if (!counterSignList.isEmpty()) {
if (counterSignList.size() == 1) {
counterSignList.get(0).sign(rgbProtected, rgbContent);
addAttribute(HeaderKeys.CounterSignature, counterSignList.get(0).EncodeToCBORObject(), Attribute.UNPROTECTED);
}
else {
CBORObject list = CBORObject.NewArray();
for (CounterSign sig : counterSignList) {
sig.sign(rgbProtected, rgbContent);
list.Add(sig.EncodeToCBORObject());
}
addAttribute(HeaderKeys.CounterSignature, list, Attribute.UNPROTECTED);
}
}
if (counterSign1 != null) {
counterSign1.sign(rgbProtected, rgbContent);
addAttribute(HeaderKeys.CounterSignature0, counterSign1.EncodeToCBORObject(), Attribute.UNPROTECTED);
}
}
public boolean validate(CounterSign1 countersignature) throws CoseException {
return countersignature.validate(rgbProtected, rgbContent);
}
public boolean validate(CounterSign countersignature) throws CoseException {
return countersignature.validate(rgbProtected, rgbContent);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy