@Override
public Sign.SignatureData callHSM(byte[] dataToSign, HSMPass pass) {
// Create the SignRequest for AWS KMS
var signRequest =
SignRequest.builder()
.keyId(keyID)
.message(SdkBytes.fromByteArray(dataHash))
.messageType(MessageType.DIGEST)
.signingAlgorithm(SigningAlgorithmSpec.ECDSA_SHA_256)
.build();
// Sign the data using AWS KMS
var signResult = kmsClient.sign(signRequest);
var signatureBuffer = signResult.signature().asByteBuffer();
// Convert the signature to byte array
var signBytes = new byte[signatureBuffer.remaining()];
signatureBuffer.get(signBytes);
// Verify signature osn KMS
var verifyRequest =
VerifyRequest.builder()
.keyId(keyID)
.message(SdkBytes.fromByteArray(dataHash))
.messageType(MessageType.DIGEST)
.signingAlgorithm(SigningAlgorithmSpec.ECDSA_SHA_256)
.signature(SdkBytes.fromByteArray(signBytes))
.build();
var verifyRequestResult = kmsClient.verify(verifyRequest);
if (!verifyRequestResult.signatureValid()) {
throw new RuntimeException(“KMS signature is not valid!”);
}
var signature = CryptoUtils.fromDerFormat(signBytes);
return Sign.createSignatureData(signature, pass.getPublicKey(), dataHash);
}
NOTE!
In order to use this properly, the type of key spec created in AWS KMS must be ECC_SECG_P256K1. This is specific to the crypto space, especially to EVM. Using any other key will result in a mismatch error when the data signature is created.
Example
Here is a short example of how to call the callHSM method from the library:
public static void main(String[] args) throws Exception {
KmsClient client = KmsClient.create();
// extract the KMS key
byte[] derPublicKey = client
.getPublicKey((var builder) -> {
builder.keyId(kmsKeyId);
})
.publicKey()
.asByteArray();
byte[] rawPublicKey = SubjectPublicKeyInfo
.getInstance(derPublicKey)
.getPublicKeyData()
.getBytes();
BigInteger publicKey = new BigInteger(1, Arrays.copyOfRange(rawPublicKey, 1, rawPublicKey.length));
HSMPass pass = new HSMPass(null, publicKey);
HSMRequestProcessor signer = new HSMAwsKMSRequestProcessor(client, kmsKeyId);
signer.callHSM(data, pass);
}
Conclusion
AWS KMS, with its built-in HSM functionality, offers a powerful solution for securely managing and signing cryptographic transactions. Despite initial challenges faced by users in integrating AWS KMS with Hyperledger Web3j, the introduction of the HSMAwsKMSRequestProcessor class has made it easier to adopt and implement. This ready-to-use solution simplifies interactions with AWS KMS, allowing users to securely sign data and transactions with minimal configuration. By leveraging this tool, organizations can enhance their security posture while benefiting from the convenience of AWS’s cloud-native HSM capabilities.