/* * 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.util.ArrayList; import java.util.List; /** * The Signer class is used to implement the COSE_Signer object. * This provides the information dealing with a single signature for the SignMessage class. *
* Create a Signer object for adding a new signature to a message, existing signers will have a Signer object created for them when a SignMessage object is created by Message.DecodeFromBytes. *
* Examples of using this class can be found in
*
Single Signer Example an example of signing and verify a message with a single signature.
*
Multiple Signer Example an example of signing and verifying a message which has multiple signatures.
* @author jimsch
*/
public class Signer extends Attribute {
protected byte[] rgbSignature;
protected String contextString;
OneKey cnKey;
/**
* Create a new signer object to add to a SignMessage
*/
public Signer() {
contextString = "Signature";
}
/**
* Create a new signer object for a SignMessage and set the key to be used.
*
* @param key key to use for signing.
*/
public Signer(OneKey key) {
contextString = "Signature";
cnKey = key;
}
/**
* Remove the key object from the signer
*
* @since COSE 0.9.1
*/
public void clearKey() {
cnKey = null;
}
/**
* Set a key object on a signer
*
* @since COSE 0.9.1
* @param keyIn key to be used for signing or verification
* @throws CoseException - Invalid key passed in
*/
public void setKey(OneKey keyIn) throws CoseException {
setupKey(keyIn);
}
/**
* Set the key on the object, if there is not a signature on this object then set
* the algorithm and the key id from the key if they exist on the key and do not exist in the message.
*
* @param key key to be used]
*/
private void setupKey(OneKey key) throws CoseException {
CBORObject cn2;
CBORObject cn;
cnKey = key;
if (rgbSignature != null) return;
cn = key.get(KeyKeys.Algorithm);
if (cn != null) {
cn2 = findAttribute(HeaderKeys.Algorithm);
if (cn2 == null) addAttribute(HeaderKeys.Algorithm, cn, Attribute.PROTECTED);
}
cn = key.get(KeyKeys.KeyId);
if (cn != null) {
cn2 = findAttribute(HeaderKeys.KID);
if (cn2 == null) addAttribute(HeaderKeys.KID, cn, Attribute.UNPROTECTED);
}
}
/**
* Internal function used in creating a Sign1Message object from a byte string.
*
* @param obj COSE_Sign1 encoded object.
* @throws CoseException Errors generated by the COSE module
*/
protected void DecodeFromCBORObject(CBORObject obj) throws CoseException {
if (obj.getType() != CBORType.Array) throw new CoseException("Invalid Signer structure");
if (obj.size() != 3) throw new CoseException("Invalid Signer structure");
if (obj.get(0).getType() == CBORType.ByteString) {
rgbProtected = obj.get(0).GetByteString();
if (rgbProtected.length == 0) {
objProtected = CBORObject.NewMap();
}
else {
objProtected = CBORObject.DecodeFromBytes(rgbProtected);
if (objProtected.size() == 0) rgbProtected = new byte[0];
}
}
else throw new CoseException("Invalid Signer structure");
if (obj.get(1).getType() == CBORType.Map) {
objUnprotected = obj.get(1);
}
else throw new CoseException("Invalid Signer structure");
if (obj.get(2).getType() == CBORType.ByteString) rgbSignature = obj.get(2).GetByteString();
else if (!obj.get(2).isNull()) throw new CoseException("Invalid Signer structure");
CBORObject countersignature = this.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 csObj : countersignature.getValues()) {
if (csObj.getType() != CBORType.Array) {
throw new CoseException("Invalid countersignature attribute");
}
CounterSign cs = new CounterSign(csObj);
cs.setObject(this);
this.addCountersignature(cs);
}
}
else {
CounterSign cs = new CounterSign(countersignature);
cs.setObject(this);
this.addCountersignature(cs);
}
}
countersignature = this.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(this);
this.counterSign1 = cs;
}
}
/**
* Internal function used to create a serialization of a COSE_Sign1 message
*
* @return CBOR object which can be encoded.
* @throws CoseException Errors generated by the COSE module
*/
protected CBORObject EncodeToCBORObject() throws CoseException {
if (rgbSignature == null) throw new CoseException("Message not yet signed");
if (rgbProtected == null) throw new CoseException("Internal Error");
CBORObject obj = CBORObject.NewArray();
obj.Add(rgbProtected);
obj.Add(objUnprotected);
obj.Add(rgbSignature);
return obj;
}
public void sign(byte[] rgbBodyProtected, byte[] rgbContent) throws CoseException
{
if (rgbProtected == null) {
if(objProtected.size() == 0) rgbProtected = new byte[0];
else rgbProtected = objProtected.EncodeToBytes();
}
CBORObject obj = CBORObject.NewArray();
obj.Add(contextString);
obj.Add(rgbBodyProtected);
obj.Add(rgbProtected);
obj.Add(externalData);
obj.Add(rgbContent);
AlgorithmID alg = AlgorithmID.FromCBOR(findAttribute(HeaderKeys.Algorithm));
rgbSignature = SignCommon.computeSignature(alg, obj.EncodeToBytes(), cnKey);
ProcessCounterSignatures();
}
public boolean validate(byte[] rgbBodyProtected, byte[] rgbContent) throws CoseException
{
CBORObject obj = CBORObject.NewArray();
obj.Add(contextString);
obj.Add(rgbBodyProtected);
obj.Add(rgbProtected);
obj.Add(externalData);
obj.Add(rgbContent);
AlgorithmID alg = AlgorithmID.FromCBOR(findAttribute(HeaderKeys.Algorithm));
return SignCommon.validateSignature(alg, obj.EncodeToBytes(), rgbSignature, cnKey);
}
List