amazon-kmsaws-java-sdksymmetric-keyhmacsha256

Java API for generating and verifying MAC using AWS KMS key


Essentially, I want to perform this "Sign" mechanism for a symmetric - in particular HMAC - key that I've generated in my AWS KMS (CMK). But obviously, the SignRequest or SignResponse classes in that example only support Asymmetric keys, so I'm wondering what would be the equivalent classes to do this for symmetric keys? I found this GenerateKey API as the only API way of signing with HMAC keys, but the example doesn't provide all details (has only an example request body). Where are we actually sending the request/how do we authenticate?

In summary, need to know how to sign a message/generate a mac with an KMS HMAC key that I already have in my KMS. P.S. I've been able to do what I want (see below) on the command line. Just need an API way of doing it.

% aws kms generate-mac --message fileb://aws-test.txt --key-id <keyId> --mac-algorithm HMAC_SHA_256                                                 
{
    "Mac": "<mac>",
    "MacAlgorithm": "HMAC_SHA_256",
    "KeyId": "arn:aws:kms:<region>:<....>:key/<keyId>"
}
user@user-mac  
% aws kms verify-mac --message fileb://aws-test.txt --key-id <keyId> --mac-algorithm HMAC_SHA_256 --mac <mac>
{
    "KeyId": "arn:aws:kms:<region>:<....>:key/<keyId>",
    "MacValid": true,
    "MacAlgorithm": "HMAC_SHA_256"
}
user@user-mac 

P.S. I successfully used aws-sdk:kms to create and upload the HMAC keys in my KMS.


Solution

  • Okay, I found the answer. The way to it is with these four classes - GenerateMacRequest, GenerateMacResponse, VerifyMacRequest, and VerifyMacResponse. See example code below.

    I have no idea why AWS documentation would be so cryptic - this page I had linked above makes no mention of the actual corresponding API method and instead just leads people astray into thinking one has to build a request from scratch and provide url and request params.

    // define `msgToSign`, `keyId`, `algorithm`
    String algorithm = "HMAC_SHA_256";
    String keyId = "<your-created-keyId>";
    String msgToSign = "Hello, World!"
    
    SdkBytes bytes = SdkBytes.fromString(msgToSign, Charset.defaultCharset());
    
    GenerateMacRequest rq = GenerateMacRequest.builder()
                .keyId(keyId)
                .message(bytes)
                .macAlgorithm(algorithm)
                .build();
    
    GenerateMacResponse rs = kmsClient.generateMac(rq);
    
    String macStr = new String(Base64.encodeBase64(rs.mac().asByteArray()));
    System.out.println("Base64 encoded mac: " + macStr);
    
    VerifyMacRequest vmrq = VerifyMacRequest.builder()
                .keyId(keyId)
                .macAlgorithm(algorithm)
                .message(bytes)
                .mac(rs.mac())
                .build();
    
    VerifyMacResponse vmrs = kmsClient.verifyMac(vmrq);
    
    System.out.println("Mac valid? : " + vmrs.macValid());