Beispiel für Offline-Operationen - AWS Key Management Service

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Beispiel für Offline-Operationen

Nachdem Sie den öffentlichen Schlüssel Ihres asymmetrischen KMS-Schlüsselpaars heruntergeladen haben, können Sie ihn mit anderen teilen und für Offline-Operationen verwenden.

AWS CloudTrail Protokolle, die jeden AWS KMS Vorgang aufzeichnen, einschließlich der Anfrage, der Antwort, des Datums, der Uhrzeit und des autorisierten Benutzers, zeichnen nicht die Verwendung des öffentlichen Schlüssels außerhalb von AWS KMS auf.

Dieses Thema enthält Beispiele für Offline-Operationen und Einzelheiten, die die Tools AWS KMS bereitstellen, um Offline-Operationen zu vereinfachen.

Offline-Ableitung gemeinsam genutzter Geheimnisse

Sie können den öffentlichen Schlüssel Ihres ECC-Schlüsselpaars herunterladen, um ihn im Offline-Betrieb zu verwenden, d. h. bei Vorgängen außerhalb von AWS KMS.

Die folgende OpenSSL-Komplettlösung zeigt eine Methode zum Ableiten eines gemeinsamen geheimen Schlüssels außerhalb der AWS KMS Verwendung des öffentlichen Schlüssels eines ECC-KMS-Schlüsselpaars und eines mit OpenSSL erstellten privaten Schlüssels.

  1. Erstellen Sie ein ECC-Schlüsselpaar in OpenSSL und bereiten Sie es für die Verwendung mit vor. 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"`
  2. Erstellen Sie ein key pair für die ECC-Schlüsselvereinbarung AWS KMS und bereiten Sie es für die Verwendung mit OpenSSL vor.

    // 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}
  3. Leiten Sie Shared Secret in OpenSSL mithilfe des privaten Schlüssels in OpenSSL und des öffentlichen KMS-Schlüssels ab.

    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}

Offline-Überprüfung mit SM2 Schlüsselpaaren (nur Regionen China)

Um eine Signatur außerhalb oder AWS KMS mit einem SM2 öffentlichen Schlüssel zu verifizieren, müssen Sie die identifizierende ID angeben. Wenn Sie eine Rohnachricht an die Sign-API übergeben MessageType:RAW, AWS KMS verwendet sie die standardmäßige Unterscheidungs-ID1234567812345678, die von OSCCA in GM/T 0009-2012 definiert wurde. Sie können nicht Ihre eigene unterscheidende ID in AWS KMS angeben.

Wenn Sie jedoch einen Nachrichtenüberblick außerhalb von generieren AWS, können Sie Ihre eigene Unterscheidungs-ID angeben und dann den Nachrichtenüberblick,, zum Signieren an übergeben. MessageType:DIGEST AWS KMS Dafür ändern Sie den DEFAULT_DISTINGUISHING_ID-Wert in der SM2OfflineOperationHelper-Klasse. Die von Ihnen angegebene Unterscheidungs-ID kann eine beliebige Zeichenfolge mit einer Länge von bis zu 8.192 Zeichen sein. Nachdem Sie den Message Digest AWS KMS signiert haben, benötigen Sie entweder den Message Digest oder die Nachricht und die Unterscheidungs-ID, die zur Berechnung des Digest verwendet wurde, um ihn offline zu verifizieren.

Wichtig

Der SM2OfflineOperationHelper-Referenzcode ist so konzipiert, dass er kompatibel mit Bouncy CastleVersion 1.68 ist. Für Hilfe zu anderen Versionen wenden Sie sich an bouncycastle.org.

SM2OfflineOperationHelper-Klasse

Um Ihnen bei Offline-Operationen mit SM2 Schlüsseln zu helfen, verfügt die SM2OfflineOperationHelper Klasse für Java über Methoden, die die Aufgaben für Sie ausführen. Sie können diese Hilfsklasse als Modell für andere kryptografische Anbieter verwenden.

Darin werden die AWS KMS unformatierten Chiffretext-Konvertierungen und die SM2 DSA-Message-Digest-Berechnungen automatisch durchgeführt. Nicht alle Kryptografieanbieter implementieren SM2 sie auf die gleiche Weise. Einige Bibliotheken, wie OpenSSL-Versionen 1.1.1 und höher, führen diese Aktionen automatisch aus. AWS KMS bestätigte dieses Verhalten beim Testen mit OpenSSL Version 3.0. Verwenden Sie die folgende SM2OfflineOperationHelper-Klasse mit Bibliotheken, wie Bouncy Castle, bei denen Sie diese Konvertierungen und Berechnungen manuell durchführen müssen.

Die SM2OfflineOperationHelper-Klasse bietet Methoden für die folgenden Offline-Vorgänge:

  • Message-Digest-Berechnung

    Verwenden Sie die Methode, um offline einen Nachrichtenüberblick zu generieren, den Sie für die Offline-Überprüfung verwenden oder an den calculateSM2Digest Sie AWS KMS zum Signieren übergeben können. Die calculateSM2Digest Methode generiert mithilfe des SM3 Hashing-Algorithmus einen Nachrichten-Digest. Die GetPublicKeyAPI gibt Ihren öffentlichen Schlüssel im Binärformat zurück. Sie müssen den Binärschlüssel in ein PublicKey Java-Format parsen. Stellen Sie den geparsten öffentlichen Schlüssel mit der Nachricht bereit. Die Methode kombiniert Ihre Nachricht automatisch mit der standardmäßigen Unterscheidungs-ID, 1234567812345678, aber Sie können Ihre eigene Unterscheidungs-ID festlegen, indem Sie den DEFAULT_DISTINGUISHING_ID-Wert ändern.

  • Verify

    Um eine Signatur offline zu prüfen, verwenden Sie die offlineSM2DSAVerify-Methode. Die offlineSM2DSAVerify-Methode verwendet den Message Difest, der anhand der angegebenen unterscheidenden ID berechnet wurde, und die ursprüngliche Nachricht, die Sie zur Überprüfung der digitalen Signatur bereitstellen. Die GetPublicKeyAPI gibt Ihren öffentlichen Schlüssel im Binärformat zurück. Sie müssen den Binärschlüssel in ein PublicKey Java-Format parsen. Stellen Sie den geparsten öffentlichen Schlüssel mit der ursprünglichen Nachricht und der Signatur, die Sie überprüfen möchten, bereit. Weitere Informationen finden Sie unter Offline-Überprüfung mit SM2 Schlüsselpaaren.

  • Encrypt

    Um Klartext offline zu verschlüsseln, verwenden Sie die offlineSM2PKEEncrypt-Methode. Diese Methode stellt sicher, dass der Chiffretext in einem Format vorliegt, das entschlüsselt AWS KMS werden kann. Die offlineSM2PKEEncrypt Methode verschlüsselt den Klartext und konvertiert dann den von PKE erzeugten Rohchiffretext in das ASN.1-Format. SM2 Die GetPublicKeyAPI gibt Ihren öffentlichen Schlüssel im Binärformat zurück. Sie müssen den Binärschlüssel in ein PublicKey Java-Format parsen. Versehen Sie den geparsten öffentlichen Schlüssel mit dem Klartext, den Sie verschlüsseln möchten.

    Wenn Sie sich nicht sicher sind, ob Sie die Konvertierung durchführen müssen, verwenden Sie den folgenden OpenSSL-Vorgang, um das Format Ihres Geheimtextes zu testen. Wenn der Vorgang fehlschlägt, müssen Sie den Geheimtext in das ASN.1-Format konvertieren.

    openssl asn1parse -inform DER -in ciphertext.der

Standardmäßig verwendet die SM2OfflineOperationHelper Klasse beim Generieren von Nachrichtenübersichten für 1234567812345678 DSA-Operationen die standardmäßige Unterscheidungs-ID. SM2

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"); } }