Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.
Ejemplo de operaciones sin conexión
Tras descargar la clave pública de su par de claves KMS asimétricas, puede compartirla con otras personas y utilizarla para realizar operaciones sin conexión.
Registros de AWS CloudTrail que registran cada operación de AWS KMS, incluida la solicitud, la respuesta, la fecha, el tiempo y el usuario autorizado, no registran el uso de la clave pública fuera de AWS KMS.
En este tema se proporcionan ejemplos de operaciones sin conexión y se detallan las herramientas que AWS KMS proporciona para facilitar las operaciones sin conexión.
Temas
Obtención de secretos compartidos sin conexión
Puede descargar la clave pública del par de claves ECC para uso en operaciones sin conexión, es decir, operaciones fuera de AWS KMS.
En el siguiente tutorial de OpenSSL
-
Cree un par de claves ECC en OpenSSL y prepárelo para usarlo con AWS KMS.
// Create an ECC key pair in OpenSSL and save the private key in openssl_ecc_key_priv.pem export OPENSSL_CURVE_NAME="P-256" export KMS_CURVE_NAME="ECC_NIST_P256" export OPENSSL_KEY1_PRIV_PEM="openssl_ecc_key1_priv.pem" openssl ecparam -name ${OPENSSL_CURVE_NAME} -genkey -out ${OPENSSL_KEY1_PRIV_PEM} // Derive the public key from the private key export OPENSSL_KEY1_PUB_PEM="openssl_ecc_key1_pub.pem" openssl ec -in ${OPENSSL_KEY1_PRIV_PEM} -pubout -outform pem \ -out ${OPENSSL_KEY1_PUB_PEM} // View the PEM file containing the public key and extract the public key as a // Base64 encoded string into OPENSSL_KEY1_PUB_BASE64 for use with AWS KMS export OPENSSL_KEY1_PUB_BASE64=`cat ${OPENSSL_KEY1_PUB_PEM} | \ tee /dev/stderr | grep -v "PUBLIC KEY" | tr -d "\n"`
-
Cree un par de claves de acuerdo de claves ECC en AWS KMS y prepárelo para usarlo con OpenSSL.
// Create a KMS key on the same curve as the key pair from step 1 // with a key usage of KEY_AGREEMENT // Save its ARN in KMS_KEY1_ARN. export KMS_KEY1_ARN=`aws kms create-key --key-spec ${KMS_CURVE_NAME} \ --key-usage KEY_AGREEMENT | tee /dev/stderr | jq -r .KeyMetadata.Arn` // Download the public key and save the Base64-encoded version in KMS_KEY1_PUB_BASE64 export KMS_KEY1_PUB_BASE64=`aws kms get-public-key --key-id ${KMS_KEY1_ARN} | \ tee /dev/stderr | jq -r .PublicKey` // Create a PEM file for the public KMS key for use with OpenSSL export KMS_KEY1_PUB_PEM="aws_kms_ecdh_key1_pub.pem" echo "-----BEGIN PUBLIC KEY-----" > ${KMS_KEY1_PUB_PEM} echo ${KMS_KEY1_PUB_BASE64} | fold -w 64 >> ${KMS_KEY1_PUB_PEM} echo "-----END PUBLIC KEY-----" >> ${KMS_KEY1_PUB_PEM}
-
Obtenga el secreto compartido en OpenSSL mediante la clave privada de OpenSSL y la clave pública de KMS.
export OPENSSL_SHARED_SECRET1_BIN="openssl_shared_secret1.bin" openssl pkeyutl -derive -inkey ${OPENSSL_KEY1_PRIV_PEM} \ -peerkey ${KMS_KEY1_PUB_PEM} -out ${OPENSSL_SHARED_SECRET1_BIN}
Verificación sin conexión con pares de claves SM2 (solo en las regiones de China)
Para verificar una firma fuera de AWS KMS con una clave pública SM2, debe especificar el identificador distintivo. Cuando pasa un mensaje sin formato, MessageType:RAW
, a la API Sign, AWS KMS utiliza el identificador distintivo predeterminado, 1234567812345678
, definido por la OSCCA en GM/T 0009-2012. No puede especificar su propio identificador distintivo en AWS KMS.
Sin embargo, si está generando un resumen de mensajes fuera de AWS, puede especificar su propio identificador distintivo y, a continuación, pasar el resumen del mensaje, MessageType:DIGEST
, a AWS KMS para su firma. Para ello, cambie el valor DEFAULT_DISTINGUISHING_ID
en la clase SM2OfflineOperationHelper
. El identificador distintivo que especifique puede ser cualquier cadena de hasta 8192 caracteres. Después de que AWS KMS firma el resumen del mensaje, necesita el resumen del mensaje o el mensaje y el identificador distintivo utilizados para calcular el resumen y verificarlo sin conexión.
importante
El código de referencia SM2OfflineOperationHelper
está diseñado para ser compatible con Bouncy Castle
Clase SM2OfflineOperationHelper
Para ayudarle con las operaciones sin conexión con claves SM2, la clase SM2OfflineOperationHelper
para Java tiene métodos que realizan las tareas por usted. Puede usar esta clase auxiliar como modelo para otros proveedores de cifrado.
Dentro de AWS KMS, las conversiones de texto cifrado sin procesar y los cálculos de resumen de mensajes SM2DSA se producen automáticamente. No todos los proveedores de cifrado implementan SM2 de la misma manera. Algunas bibliotecas, como OpenSSLSM2OfflineOperationHelper
con bibliotecas, como Bouncy Castle
La clase SM2OfflineOperationHelper
proporciona métodos para las siguientes operaciones fuera de línea:
-
- Cálculo del resumen del mensaje
-
Para generar un resumen de mensajes sin conexión que pueda usar para la verificación sin conexión o que pueda pasar a AWS KMS para su firma, utilice el método
calculateSM2Digest
. El métodocalculateSM2Digest
genera un resumen de mensajes con el algoritmo hash SM3. La API de GetPublicKey devuelve la clave pública en formato binario. Debe analizar la clave binaria en una PublicKey de Java. Proporcione la clave pública analizada con el mensaje. El método combina automáticamente el mensaje con el identificador distintivo predeterminado,1234567812345678
, pero puede establecer su propio identificador distintivo cambiando el valorDEFAULT_DISTINGUISHING_ID
.
-
- Verificar
-
Para verificar una firma sin conexión, utilice el método
offlineSM2DSAVerify
. El métodoofflineSM2DSAVerify
utiliza el resumen del mensaje calculado a partir del identificador distintivo especificado y el mensaje original que proporciona para verificar la firma digital. La API de GetPublicKey devuelve la clave pública en formato binario. Debe analizar la clave binaria en una PublicKey de Java. Proporcione la clave pública analizada con el mensaje original y la firma que desea verificar. Para obtener más información, consulte Verificación sin conexión con pares de claves SM2.
-
- Encrypt
-
Para cifrar texto sin formato sin conexión, utilice el método
offlineSM2PKEEncrypt
. Este método garantiza que el texto cifrado esté en un formato que AWS KMS puede descifrar. El métodoofflineSM2PKEEncrypt
cifra el texto sin formato y, a continuación, convierte el texto cifrado sin procesar producido por SM2PKE al formato ASN.1. La API de GetPublicKey devuelve la clave pública en formato binario. Debe analizar la clave binaria en una PublicKey de Java. Proporcione la clave pública analizada con el texto sin formato que desea cifrar.Si no está seguro de si necesita realizar la conversión, utilice la siguiente operación de OpenSSL para probar el formato del texto cifrado. Si la operación falla, debe convertir el texto cifrado al formato ASN.1.
openssl asn1parse -inform DER -in
ciphertext.der
De forma predeterminada, la clase SM2OfflineOperationHelper
usa el identificador distintivo predeterminado, 1234567812345678
, al generar resúmenes de mensajes para operaciones SM2DSA.
package com.amazon.kms.utils; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import java.io.IOException; import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.PublicKey; import org.bouncycastle.crypto.CryptoException; import org.bouncycastle.jce.interfaces.ECPublicKey; import java.util.Arrays; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.gm.GMNamedCurves; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.params.ParametersWithID; import org.bouncycastle.crypto.params.ParametersWithRandom; import org.bouncycastle.crypto.signers.SM2Signer; import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; public class SM2OfflineOperationHelper { // You can change the DEFAULT_DISTINGUISHING_ID value to set your own distinguishing ID, // the DEFAULT_DISTINGUISHING_ID can be any string up to 8,192 characters long. private static final byte[] DEFAULT_DISTINGUISHING_ID = "1234567812345678".getBytes(StandardCharsets.UTF_8); private static final X9ECParameters SM2_X9EC_PARAMETERS = GMNamedCurves.getByName("sm2p256v1"); // ***calculateSM2Digest*** // Calculate message digest public static byte[] calculateSM2Digest(final PublicKey publicKey, final byte[] message) throws NoSuchProviderException, NoSuchAlgorithmException { final ECPublicKey ecPublicKey = (ECPublicKey) publicKey; // Generate SM3 hash of default distinguishing ID, 1234567812345678 final int entlenA = DEFAULT_DISTINGUISHING_ID.length * 8; final byte [] entla = new byte[] { (byte) (entlenA & 0xFF00), (byte) (entlenA & 0x00FF) }; final byte [] a = SM2_X9EC_PARAMETERS.getCurve().getA().getEncoded(); final byte [] b = SM2_X9EC_PARAMETERS.getCurve().getB().getEncoded(); final byte [] xg = SM2_X9EC_PARAMETERS.getG().getXCoord().getEncoded(); final byte [] yg = SM2_X9EC_PARAMETERS.getG().getYCoord().getEncoded(); final byte[] xa = ecPublicKey.getQ().getXCoord().getEncoded(); final byte[] ya = ecPublicKey.getQ().getYCoord().getEncoded(); final byte[] za = MessageDigest.getInstance("SM3", "BC") .digest(ByteBuffer.allocate(entla.length + DEFAULT_DISTINGUISHING_ID.length + a.length + b.length + xg.length + yg.length + xa.length + ya.length).put(entla).put(DEFAULT_DISTINGUISHING_ID).put(a).put(b).put(xg).put(yg).put(xa).put(ya) .array()); // Combine hashed distinguishing ID with original message to generate final digest return MessageDigest.getInstance("SM3", "BC") .digest(ByteBuffer.allocate(za.length + message.length).put(za).put(message) .array()); } // ***offlineSM2DSAVerify*** // Verify digital signature with SM2 public key public static boolean offlineSM2DSAVerify(final PublicKey publicKey, final byte [] message, final byte [] signature) throws InvalidKeyException { final SM2Signer signer = new SM2Signer(); CipherParameters cipherParameters = ECUtil.generatePublicKeyParameter(publicKey); cipherParameters = new ParametersWithID(cipherParameters, DEFAULT_DISTINGUISHING_ID); signer.init(false, cipherParameters); signer.update(message, 0, message.length); return signer.verifySignature(signature); } // ***offlineSM2PKEEncrypt*** // Encrypt data with SM2 public key public static byte[] offlineSM2PKEEncrypt(final PublicKey publicKey, final byte [] plaintext) throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException { final Cipher sm2Cipher = Cipher.getInstance("SM2", "BC"); sm2Cipher.init(Cipher.ENCRYPT_MODE, publicKey); // By default, Bouncy Castle returns raw ciphertext in the c1c2c3 format final byte [] cipherText = sm2Cipher.doFinal(plaintext); // Convert the raw ciphertext to the ASN.1 format before passing it to AWS KMS final ASN1EncodableVector asn1EncodableVector = new ASN1EncodableVector(); final int coordinateLength = (SM2_X9EC_PARAMETERS.getCurve().getFieldSize() + 7) / 8 * 2 + 1; final int sm3HashLength = 32; final int xCoordinateInCipherText = 33; final int yCoordinateInCipherText = 65; byte[] coords = new byte[coordinateLength]; byte[] sm3Hash = new byte[sm3HashLength]; byte[] remainingCipherText = new byte[cipherText.length - coordinateLength - sm3HashLength]; // Split components out of the ciphertext System.arraycopy(cipherText, 0, coords, 0, coordinateLength); System.arraycopy(cipherText, cipherText.length - sm3HashLength, sm3Hash, 0, sm3HashLength); System.arraycopy(cipherText, coordinateLength, remainingCipherText, 0,cipherText.length - coordinateLength - sm3HashLength); // Build standard SM2PKE ASN.1 ciphertext vector asn1EncodableVector.add(new ASN1Integer(new BigInteger(1, Arrays.copyOfRange(coords, 1, xCoordinateInCipherText)))); asn1EncodableVector.add(new ASN1Integer(new BigInteger(1, Arrays.copyOfRange(coords, xCoordinateInCipherText, yCoordinateInCipherText)))); asn1EncodableVector.add(new DEROctetString(sm3Hash)); asn1EncodableVector.add(new DEROctetString(remainingCipherText)); return new DERSequence(asn1EncodableVector).getEncoded("DER"); } }