Как проверить цифровую подпись за пределами AWS, используя java API безопасности, если я использовал AWS KMS-сервис для создания подписи? - PullRequest
0 голосов
/ 11 января 2020

Я использовал AWS KMS для создания подписи. Теперь мне нужно проверить подпись вне AWS, используя java API безопасности. Хотя я могу успешно получить ключ publi c, метод verify каждый раз возвращает false. Я использовал bouncycastleprovider, но не увенчался успехом. Какие другие провайдеры я могу использовать для проверки?

1 Ответ

0 голосов
/ 12 февраля 2020

Я начну сверху, потому что то, как вы делаете запрос 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);

Надеюсь, это поможет! Я не так много знаю о криптографии, как следовало бы, и, возможно, испортил некоторую терминологию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...