All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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