Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ public enum SignatureErrorCode {

CLAIM_NOT_FOUND("KER-SIG-118", "{claim} Claim not found in the CWT Token."),

CLAIM_NOT_MATCHED("KER-SIG-119", "Provided {claim} Claim value not matched with CWT.");
CLAIM_NOT_MATCHED("KER-SIG-119", "Provided {claim} Claim value not matched with CWT."),

UNTAGGED_COSE_SIGN1("KER-SIG-120", "Untagged COSE Sign1 not found"),

TAGGED_COSE_SIGN1("KER-SIG-121", "Tagged COSE Sign1 not found");

private final String errorCode;
private final String errorMessage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public class CoseSignController {
@ResponseFilter
@PreAuthorize("hasAnyRole(@signAuthRoles.getPostcosesign1())")
@PostMapping(value = "/coseSign1")
public ResponseWrapper<CoseSignResponseDto> coseSign(@RequestBody @Valid RequestWrapper<CoseSignRequestDto> requestDto) {
public ResponseWrapper<CoseSignResponseDto> coseSign1(@RequestBody @Valid RequestWrapper<CoseSignRequestDto> requestDto) {
CoseSignResponseDto coseSignResponse = service.coseSign1(requestDto.getRequest());
ResponseWrapper<CoseSignResponseDto> response = new ResponseWrapper<>();
response.setResponse(coseSignResponse);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
public class CoseSignRequestDto {

@NotBlank
@ApiModelProperty(notes = "Base64 encoded Data to sign", example = "ewogICAiYW55S2V5IjogIlRlc3QgSnNvbiIKfQ", required = true)
@ApiModelProperty(notes = "Base64URL encoded Data to sign", example = "ewogICAiYW55S2V5IjogIlRlc3QgSnNvbiIKfQ", required = true)
private String payload;

/**
Expand Down Expand Up @@ -46,4 +46,10 @@ public class CoseSignRequestDto {
*/
@ApiModelProperty(notes = "Algorithm to use for data signing", example = "PS256", required = false)
private String algorithm;

/**
* Include COSE Tag
*/
@ApiModelProperty(notes = "Include COSE Tag", example = "true", required = false)
private Boolean includeCOSETag;
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ public class CoseSignVerifyRequestDto {
@ApiModelProperty(notes = "Certificate to be use in JWT Signature verification.", example = "", required = false)
private String certificateData;

/**
* Flag to validate the COSE TAG.
*/
@ApiModelProperty(notes = "Flag to validate the COSE TAG.", example = "true", required = false)
private Boolean isCOSETagIncluded;
/**
* Flag to validate against trust store.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@
public interface CoseSignatureService {

/**
* COSE Sign
* COSE Sign1
*
* @param coseSignRequestDto the COSESignRequestDto
* @return the COSESignResponseDto
*/
public CoseSignResponseDto coseSign1(CoseSignRequestDto coseSignRequestDto);

/**
* COSE Verify
* COSE Verify1
*
* @param coseSignVerifyRequestDto the COSESignVerifyRequestDto
* @return the COSESignVerifyResponseDto
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
Expand Down Expand Up @@ -114,7 +113,7 @@ public CoseSignResponseDto coseSign1(CoseSignRequestDto coseSignRequestDto) {
SignatureErrorCode.INVALID_INPUT.getErrorMessage());
}

String payload = new String(CryptoUtil.decodeURLSafeBase64(base64Payload));
byte[] payload = CryptoUtil.decodeURLSafeBase64(base64Payload);

String timestamp = DateUtils.getUTCCurrentDateTimeString();
String applicationId = coseSignRequestDto.getApplicationId();
Expand All @@ -125,7 +124,7 @@ public CoseSignResponseDto coseSign1(CoseSignRequestDto coseSignRequestDto) {
}

SignatureCertificate certificateResponse = keymanagerService.getSignatureCertificate(applicationId, Optional.of(referenceId), timestamp);
String signedData = signCose1(payload.getBytes(StandardCharsets.UTF_8), certificateResponse, referenceId, coseSignRequestDto, false);
String signedData = signCose1(payload, certificateResponse, referenceId, coseSignRequestDto, false);

CoseSignResponseDto responseDto = new CoseSignResponseDto();
responseDto.setSignedData(signedData);
Expand Down Expand Up @@ -170,7 +169,8 @@ private String signCose1(byte[] cosePayload, SignatureCertificate certificateRes
.signature(signature)
.build();

return bytesToHex(encodeTaggedCoseSign1(coseSign1, isCwt));
boolean includeCoseTag = !Boolean.FALSE.equals(requestDto.getIncludeCOSETag());
return bytesToHex(encodeTaggedCoseSign1(coseSign1, isCwt, includeCoseTag));
} catch (IOException e) {
LOGGER.error(SignatureConstant.SESSIONID, SignatureConstant.COSE_SIGN, SignatureConstant.BLANK,
"Error occurred while signing COSE data.", e);
Expand All @@ -179,10 +179,14 @@ private String signCose1(byte[] cosePayload, SignatureCertificate certificateRes
}
}

private byte[] encodeTaggedCoseSign1(COSESign1 coseSign1, boolean isCwt) throws IOException {
private byte[] encodeTaggedCoseSign1(COSESign1 coseSign1, boolean isCwt, boolean includeCoseTag) throws IOException {
byte[] coseBytes = coseSign1.encode();
CBORDecoder decoder = new CBORDecoder(coseBytes);
CBORItem coseItem = decoder.next();

if (!includeCoseTag)
return coseItem.encode();

CBORTaggedItem sign1Tagged = new CBORTaggedItem(SignatureConstant.COSE_SIGN1_TAG, coseItem);

if (isCwt) {
Expand All @@ -202,7 +206,7 @@ public CoseSignVerifyResponseDto coseVerify1(CoseSignVerifyRequestDto requestDto
String coseHexdata = requestDto.getCoseSignedData();
if (!SignatureUtil.isDataValid(coseHexdata)) {
LOGGER.error(SignatureConstant.SESSIONID, SignatureConstant.COSE_VERIFY, SignatureConstant.BLANK,
"Provided COSE data is invalid.");
"Provided COSE Signed data is invalid.");
throw new RequestException(SignatureErrorCode.INVALID_VERIFY_INPUT.getErrorCode(),
SignatureErrorCode.INVALID_VERIFY_INPUT.getErrorMessage());
}
Expand All @@ -217,15 +221,14 @@ public CoseSignVerifyResponseDto coseVerify1(CoseSignVerifyRequestDto requestDto

byte[] coseData = signatureUtil.decodeHex(coseHexdata);
CBORDecoder cborDecoder = new CBORDecoder(coseData);
CBORTaggedItem cborTaggedItem = (CBORTaggedItem) cborDecoder.next();
if ((int)cborTaggedItem.getTagNumber() != SignatureConstant.COSE_SIGN1_TAG) {
LOGGER.error(SignatureConstant.SESSIONID, SignatureConstant.COSE_VERIFY, SignatureConstant.BLANK,
"Provided CWT data does not have COSE Sign1 Array tag." + " CWT Tag Number: " + cborTaggedItem.getTagNumber());
throw new RequestException(SignatureErrorCode.INVALID_COSE_SIGN1_INPUT.getErrorCode(),
SignatureErrorCode.INVALID_COSE_SIGN1_INPUT.getErrorMessage());
}
boolean isIncludeCoseTag = !Boolean.FALSE.equals(requestDto.getIsCOSETagIncluded());

COSESign1 coseSign1;
if (isIncludeCoseTag)
coseSign1 = parseTaggedCoseSign1(cborDecoder);
else
coseSign1 = parseUntaggedCoseSign1(cborDecoder);

COSESign1 coseSign1 = (COSESign1) cborTaggedItem.getTagContent();
boolean signatureValid = verifyCoseSignature(coseSign1, reqCertData, applicationId, referenceId);
LOGGER.info(SignatureConstant.SESSIONID, SignatureConstant.COSE_VERIFY, SignatureConstant.BLANK,
"COSE Signature Verification Status: " + signatureValid);
Expand All @@ -235,9 +238,9 @@ public CoseSignVerifyResponseDto coseVerify1(CoseSignVerifyRequestDto requestDto
responseDto.setMessage(signatureValid ? SignatureConstant.VALIDATION_SUCCESSFUL : SignatureConstant.VALIDATION_FAILED);
responseDto.setTrustValid(validateTrustForCose(applicationId, referenceId, coseSign1, reqCertData, requestDto));
return responseDto;
} catch (IOException e) {
} catch (Exception e) {
LOGGER.error(SignatureConstant.SESSIONID, SignatureConstant.COSE_VERIFY, SignatureConstant.BLANK,
"Error occurred while verifying COSE data.", e);
"COSE Verification failed due to error: {}", e.getMessage(), e);
throw new SignatureFailureException(SignatureErrorCode.COSE_VERIFY_ERROR.getErrorCode(),
SignatureErrorCode.COSE_VERIFY_ERROR.getErrorMessage(), e);
}
Expand Down Expand Up @@ -630,4 +633,39 @@ private void basicCWTChecks(Map<Object, Object> payloadMap, CWTVerifyRequestDto
}
}
}

public static COSESign1 parseTaggedCoseSign1(CBORDecoder cborDecoder) {
LOGGER.info(SignatureConstant.SESSIONID, SignatureConstant.BLANK, SignatureConstant.BLANK,
"Parsing COSE Sign1 Tagged Content.");
CBORTaggedItem cborTaggedItem;
try {
cborTaggedItem = (CBORTaggedItem) cborDecoder.next();
if ((int) cborTaggedItem.getTagNumber() != SignatureConstant.COSE_SIGN1_TAG) {
LOGGER.error(SignatureConstant.SESSIONID, SignatureConstant.COSE_VERIFY, SignatureConstant.BLANK,
"Provided COSE data does not have COSE Sign1 Array tag." + " Tag Number: " + cborTaggedItem.getTagNumber());
throw new RequestException(SignatureErrorCode.INVALID_COSE_SIGN1_INPUT.getErrorCode(),
SignatureErrorCode.INVALID_COSE_SIGN1_INPUT.getErrorMessage());
}
} catch (IOException e) {
LOGGER.error(SignatureConstant.SESSIONID, SignatureConstant.COSE_VERIFY, SignatureConstant.BLANK,
"Error occurred while parsing COSE Sign1 Tagged Content" + e);
throw new RequestException(SignatureErrorCode.TAGGED_COSE_SIGN1.getErrorCode(),
SignatureErrorCode.TAGGED_COSE_SIGN1.getErrorMessage());
}
return (COSESign1) cborTaggedItem.getTagContent();
}

public static COSESign1 parseUntaggedCoseSign1(CBORDecoder cborDecoder) {
LOGGER.info(SignatureConstant.SESSIONID, SignatureConstant.BLANK, SignatureConstant.BLANK,
"Parsing COSE Sign1 Untagged Content.");
try {
CBORItem cborItem = cborDecoder.next();
return COSESign1.build(cborItem);
} catch (IOException | COSEException e) {
LOGGER.error(SignatureConstant.SESSIONID, SignatureConstant.COSE_VERIFY, SignatureConstant.BLANK,
"Error occurred while parsing COSE Sign1 Untagged Content" + e);
throw new RequestException(SignatureErrorCode.UNTAGGED_COSE_SIGN1.getErrorCode(),
SignatureErrorCode.UNTAGGED_COSE_SIGN1.getErrorMessage());
}
}
}
Loading