aws-samples / aws-cloudhsm-jce-examples

Sample applications demonstrating how to use the CloudHSM JCE
MIT No Attribution
36 stars 56 forks source link

CMAC Calculation using AWS HSM java SDK (JCE) #83

Closed rushikesh1980 closed 3 months ago

rushikesh1980 commented 6 months ago

I would like to generate CMAC using AWS HSM java SDK

I would like to calculate CMAC value according to attached file out of method available which method i should use to calculate CMAC earlier i had used digest method but when I compared the result with online CMAC generator it was not matching with CMAC generated programmatically Need your assistance here

Please have a look at my below code and tell me which method I should use

package com.trimble.crypto.cmac;

import com.amazonaws.cloudhsm.jce.provider.CloudHsmProvider; import com.trimble.crypto.util.IntializeCloudHSM; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.engines.AESEngine; import org.bouncycastle.crypto.macs.CMac; import org.bouncycastle.crypto.params.KeyParameter;

import javax.crypto.; import javax.crypto.spec.SecretKeySpec; import java.nio.ByteBuffer; import java.security.; import java.util.Base64;

public class CMACCalculator {

private static final String ALGORITHM = "AESCMAC";

public  static byte[] digest(byte[] message, Key key, String algorithm, String provider)
        throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException {
    Mac mac = Mac.getInstance(algorithm, provider);
    mac.init(key);
    mac.update(message);

    return mac.doFinal();
}

public  static byte[] generateCMAC(Key key , byte[] fileContent) throws Exception {

    IntializeCloudHSM.intializeCloudHSM();
   // Key key = SymmetricKeys.getKeyByLabel(label);

    byte[] cmac = calculateCMAC(key.getEncoded(), fileContent);

    byte[] combined = new byte[cmac.length + fileContent.length];
    System.out.println("CloudHSM CMAC for file is *********= " + Base64.getEncoder().encodeToString(cmac));
    ByteBuffer byteBuffer = ByteBuffer.wrap(combined);
    byteBuffer.put(cmac);
    byteBuffer.put(fileContent);
    combined = byteBuffer.array();

    return combined;
}

// CMAC Functions
public  static byte[] generateCMAC(byte[] key, byte[] msg) throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding",  CloudHsmProvider.PROVIDER_NAME);
    SecretKeySpec secretKeySpec = new SecretKeySpec(key, ALGORITHM);
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
    return cipher.doFinal(msg);
}

private static byte[] calculateCMAC(byte[] keyBytes, byte[] data) throws Exception {
    BlockCipher cipher = new AESEngine();
    CMac cmac = new CMac(cipher);

    KeyParameter key = new KeyParameter(keyBytes);
    cmac.init(key);

    cmac.update(data, 0, data.length);

    byte[] result = new byte[cmac.getMacSize()];
    cmac.doFinal(result, 0);

    return result;
}

}

rday commented 6 months ago

Hi @rushikesh1980 ,

You can get the desired behavior by using AESCMAC as the algorithm in this sample: https://github.com/aws-samples/aws-cloudhsm-jce-examples/blob/sdk5/src/main/java/com/amazonaws/cloudhsm/examples/HMACOperationsRunner.java#L68.

A quick example cmac function that builds on the HMACOperationsRunner example:

public static void cmac() throws Exception {
    String plainText = "This is a sample Plain Text Message!";
    Key key = SymmetricKeys.generateAESKey(256, "HmacTest");
    String algorithm = "AESCMAC";

    byte[] cloudHsmDigest = digest(plainText.getBytes("UTF-8"), key, algorithm, CloudHsmProvider.PROVIDER_NAME);
    System.out.println("CloudHSM CMAC= " + Base64.getEncoder().encodeToString(cloudHsmDigest));
}

Give that a try and see if you can integrate it into your code. Thanks!

rday commented 3 months ago

Hopefully this worked out, please re-open if needed!