Uso de KMS para proteger la integridad de archivos
Escenario
Cuando sea necesario transmitir o almacenar de forma segura una gran cantidad de archivos (como imágenes, pólizas de seguros electrónicas y archivos importantes), puede utilizar KMS para firmar el compendio de archivos. Cuando se vuelvan a utilizar los archivos, podrá volver a calcular el compendio para verificar la firma. Asegúrese de que los archivos no sean manipulados durante la transmisión o el almacenamiento.
Solución
Crear una CMK en KMS.
Realice el compendio del archivo e invoque a la API de signos de KMS para firmar el compendio. Se obtiene el resultado de firma del compendio. Transmita o almacene el resultado de la firma de compendio, el ID de clave y el archivo juntos. La siguiente figura muestra el proceso de firma.
Antes de utilizar un archivo, es necesario comprobar su integridad para asegurarse de que no ha sido manipulado.
Vuelva a calcular el compendio del archivo e invoque a la API de verificación de KMS con el valor de firma para verificar la firma del compendio. Se obtiene el resultado de la verificación de firmas. Si se verifica la firma, el archivo no ha sido manipulado. La siguiente figura muestra el proceso de verificación de firmas.
Procedimiento
- Obtenga las AK y SK.
- ACCESS_KEY: Clave de acceso de la cuenta de Huawei. Para obtener más detalles, consulte ¿Cómo obtengo una clave de acceso (AK/SK)?
- SECRET_ACCESS_KEY: Clave de acceso secreta de la cuenta de Huawei. Para obtener más detalles, consulte ¿Cómo obtengo una clave de acceso (AK/SK)?
- Habrá riesgos de seguridad si la AK/SK utilizada para la autenticación se escribe directamente en el código. Cifre la AK/SK en el archivo de configuración o en las variables de entorno para su almacenamiento.
- En este ejemplo, las AK/SK almacenadas en las variables de entorno se utilizan para la autenticación de identidad. Primero configure las variables de entorno HUAWEICLOUD_SDK_AK y HUAWEICLOUD_SDK_SK en el entorno local.
- Obtenga información de la región.
- Utilice KMS para firmar el archivo y verificar la firma.
public class FileStreamSignVerifyExample { /** * Basic authentication information: * - ACCESS_KEY: access key of the Huawei Cloud account * - SECRET_ACCESS_KEY: secret access key of the Huawei Cloud account, which is sensitive information. Store this in ciphertext. * - IAM_ENDPOINT: endpoint for accessing IAM. For details, see Regions and Endpoints. * - KMS_REGION_ID: regions supported by KMS. For details, see Regions and Endpoints. * - KMS_ENDPOINT: endpoint for accessing KMS. For details, see Regions and Endpoints. */ 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>"; public static void main(String[] args) { // CMK ID. Select a key whose usage contains SIGN_VERIFY. final String keyId = args[0]; signAndVerifyFile(keyId); } /** * Use KMS to sign the file and verify the signature. * * @param keyId: CMK ID */ static void signAndVerifyFile(String keyId) { // 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. Prepare the file to be signed. // inFile File to be signed final File inFile = new File("FirstSignFile.iso"); final String fileSha256Sum = getFileSha256Sum(inFile); // 4. Calculate the digest and select a proper signature algorithm based on the key type. final SignRequest signRequest = new SignRequest().withBody( new SignRequestBody().withKeyId(keyId).withSigningAlgorithm(SignRequestBody.SigningAlgorithmEnum.RSASSA_PSS_SHA_256) .withMessageType(SignRequestBody.MessageTypeEnum.DIGEST).withMessage(fileSha256Sum)); final SignResponse signResponse = kmsClient.sign(signRequest); // 5. Verify the digest. final ValidateSignatureRequest validateSignatureRequest = new ValidateSignatureRequest().withBody( new VerifyRequestBody().withKeyId(keyId).withMessage(fileSha256Sum).withSignature(signResponse.getSignature()) .withSigningAlgorithm(VerifyRequestBody.SigningAlgorithmEnum.RSASSA_PSS_SHA_256) .withMessageType(VerifyRequestBody.MessageTypeEnum.DIGEST)); final ValidateSignatureResponse validateSignatureResponse = kmsClient.validateSignature(validateSignatureRequest); // 6. Compare the digest result. assert validateSignatureResponse.getSignatureValid().equalsIgnoreCase("true"); } /** * Calculate the SHA256 digest of the file. * * @param file * @return SHA256 digest in Base64 format */ static String getFileSha256Sum(File file) { int length; MessageDigest sha256; byte[] buffer = new byte[1024]; try { sha256 = MessageDigest.getInstance("SHA-256"); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e.getMessage()); } try (FileInputStream inputStream = new FileInputStream(file)) { while ((length = inputStream.read(buffer)) != -1) { sha256.update(buffer, 0, length); } return Base64.getEncoder().encodeToString(sha256.digest()); } catch (IOException e) { throw new RuntimeException(e.getMessage()); } } }