Я начну сверху, потому что то, как вы делаете запрос Sign для генерации подписи, влияет на то, как вы его проверяете.
Итак, у нас есть сообщение:
byte[] rawMessage = "This is my message".getBytes(StandardCharsets.UTF_8);
И нам нужно отправить его в KMS для шифрования.
Первое, что нам нужно знать, - это то, какие алгоритмы мы будем использовать для генерации подписи. Для подписей требуется как алгоритм шифрования, так и алгоритм дайджеста.
Здесь - это документ о доступных алгоритмах KMS, а здесь - соответствующая документация для Java 8. Похоже, что оба поддерживают RSA с SHA, поэтому давайте go с RSA и SHA-512. Это означает, что наш запрос Sign
должен указывать RSASSA_PKCS1_V1_5_SHA_512
в качестве алгоритма подписи, и в Java мы передадим SHA512withRSA
в Signature.getInstance .
Следующая вещь нам нужно знать, может ли размер данных, которые мы будем подписывать, превышать 4 КБ. Если это возможно, нам нужно передать MESSAGE_DIGEST
в качестве параметра MessageType
запроса на подпись, и нам также нужно будет отправить дайджест по параметру Message
вместо необработанного сообщения.
Допустим, наше сообщение может превышать 4к. Поскольку SHA-512 является нашим алгоритмом дайджеста, нам нужно получить SHA-512-дайджест наших данных:
MessageDigest digester = MessageDigest.getInstance("SHA-512");
byte[] messageDigest = digester.digest(rawMessage);
Теперь мы можем сделать наш Sign
вызов и получить подпись:
SignRequest signReq =
new SignRequest()
.withKeyId("ARN or alias of key")
.withMessageType(MessageType.DIGEST)
.withMessage(ByteBuffer.wrap(messageDigest))
.withSigningAlgorithm(RSASSA_PKCS1_V1_5_SHA_512);
SignResult signResult = kms.sign(signReq);
byte[] signatureBytes = signResult.getSignature().array();
Нам нужен ключ publi c из AWS, поэтому либо загрузите файл .pem
, либо скопируйте и вставьте ключ из консоли AWS. В любом случае, все, что нас интересует, это закодированная в base64 часть между первой и последней строками, которую мы будем использовать для создания PublicKey
объекта в криптосистеме Java:
String base64EncodedKey = "...";
byte[] pubKeyBytes = Base64.getMimeDecoder().decode(base64EncodedKey);
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(pubKeyBytes);
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(pubKeySpec);
Наконец, мы можем проверить подпись. Обратите внимание, что вы всегда будете передавать здесь все сообщение, даже если вы отправили только AWS дайджест:
Signature sig = Signature.getInstance("SHA512withRSA");
sig.initVerify(publicKey);
sig.update(rawMessage);
boolean signatureValid = sig.verify(signatureBytes);
Надеюсь, это поможет! Я не так много знаю о криптографии, как следовало бы, и, возможно, испортил некоторую терминологию.