Como usar uma chave assimétrica para verificar o resultado da assinatura de um par de chaves públicas?
Em cenários em que os pares de chaves públicas e privadas são usados, a chave privada é usada para assinatura e a chave pública é usada para verificação de assinatura. A chave pública pode ser distribuída para o sujeito do serviço que precisa usar a chave pública. O sujeito do serviço verifica a assinatura dos dados de chave. O KMS fornece a API get-publickey para obter chaves públicas.
A CMK RSA_3072 neste caso é usada para verificar assinaturas. Você pode usar o KMS para assinar APIs. O corpo da solicitação é o seguinte:
{
"key_id": "key_id_value",
"message": "MTIzNA==",
"signing_algorithm": "RSASSA_PSS_SHA_256",
"message_type": "RAW"
}
O resultado é o seguinte:
{
"key_id": "key_id_value",
"signature": "xxx"
}
Depois que a chave pública for obtida, certifique-se de que a assinatura seja verificada.
public class RawDataVerifyExample {
/**
* Basic authentication information:
* - ACCESS_KEY: access key of the Huawei Cloud account
* - SECRET_ACCESS_KEY: Huawei Cloud account secret access key, which is sensitive information. Store this in ciphertext.
* - IAM_ENDPOINT: endpoint for accessing IAM. For details, see https://developer.huaweicloud.com/intl/en-us/endpoint?IAM.
* - KMS_REGION_ID: regions supported by KMS. For details, see https://developer.huaweicloud.com/intl/en-us/endpoint?DEW.
* - KMS_ENDPOINT: endpoint for accessing KMS. For details, see https://developer.huaweicloud.com/intl/en-us/endpoint?DEW.
*/
private static final String ACCESS_KEY = System.getenv("HUAWEICLOUD_SDK_AK");
private static final String SECRET_ACCESS_KEY = System.getenv("HUAWEICLOUD_SDK_SK");
private static final String IAM_ENDPOINT = "https://<IamEndpoint>";
private static final String KMS_REGION_ID = "<RegionId>";
private static final String KMS_ENDPOINT = "https://<KmsEndpoint>";
private static final int SALT_LENGTH = 32;
private static final int TRAILER_FIELD = 1;
public static final String RSA_PUBLIC_KEY_BEGIN = "-----BEGIN PUBLIC KEY-----\n";
public static final String RSA_PUBLIC_KEY_END = "-----END PUBLIC KEY-----";
// Sample signature data in Base64 encoding format. The original text is 1234.
private static final String RWA_DATA = "MTIzNA==";
// Signature value obtained through the sign API of KMS
private static final String SIGN = "xxx";
public static void main(String[] args) throws Exception {
final String keyId = args[0];
publicKeyVerify(keyId);
}
public static void publicKeyVerify(String keyId) throws Exception {
// 1. Prepare the authentication information for accessing HUAWEI CLOUD.
final BasicCredentials auth = new BasicCredentials()
.withIamEndpoint(IAM_ENDPOINT).withAk(ACCESS_KEY).withSk(SECRET_ACCESS_KEY);
// 2. Initialize the SDK and transfer the authentication information and the address for the KMS to access the client.
final KmsClient kmsClient = KmsClient.newBuilder()
.withRegion(new Region(KMS_REGION_ID, KMS_ENDPOINT)).withCredential(auth).build();
// 3. Obtain the public key information. The returned information is in PKCS8 format.
final ShowPublicKeyRequest showPublicKeyRequest = new ShowPublicKeyRequest()
.withBody(new OperateKeyRequestBody().withKeyId(keyId));
final ShowPublicKeyResponse showPublicKeyResponse = kmsClient.showPublicKey(showPublicKeyRequest);
// 4. Obtain the public key string.
final String publicKeyStr = showPublicKeyResponse.getPublicKey().replace(RSA_PUBLIC_KEY_BEGIN, "")
.replaceAll("\n", "").replace(RSA_PUBLIC_KEY_END, "");
// 5. Parse the public key.
final X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyStr));
final KeyFactory keyFactory = KeyFactory.getInstance("RSA", new BouncyCastleProvider());
final PublicKey publicKey = keyFactory.generatePublic(keySpec);
// 6. Verify the signature.
final Signature signature = getSignature();
signature.initVerify(publicKey);
signature.update(commonHash(Base64.getDecoder().decode(RWA_DATA)));
// 7. Obtain the verification result.
assert signature.verify(Base64.getDecoder().decode(SIGN));
}
private static Signature getSignature() throws Exception {
Signature signature= Signature.getInstance("NONEwithRSASSA-PSS", new BouncyCastleProvider());
MGF1ParameterSpec mgfParam = new MGF1ParameterSpec("SHA256");
PSSParameterSpec pssParam = new PSSParameterSpec("SHA256", "MGF1", mgfParam, SALT_LENGTH, TRAILER_FIELD);
signature.setParameter(pssParam);
return signature;
}
private static byte[] commonHash(byte[] data) {
byte[] digest;
try {
MessageDigest md = MessageDigest.getInstance("SHA256", BouncyCastleProvider.PROVIDER_NAME);
md.update(data);
digest = md.digest();
} catch (Exception e) {
throw new RuntimeException("Digest failed.");
}
return digest;
}
}