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.
Themen
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
-
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"`
-
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}
-
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 ML-DSA-Schlüsselpaaren
AWS KMS unterstützt eine abgesicherte Variante der ML-DSA-Signatur, wie in Abschnitt 3.4 der Federal Information Processing Standards (FIPS) 204 beschrieben, für Nachrichten mit bis
Um Nachrichten zu signieren, die größer als 4 KB sind, führen Sie den Schritt zur Nachrichtenvorverarbeitung außerhalb von aus. AWS KMS Dieser Hashing-Schritt erstellt eine 64-Byte-Nachricht, die für μ steht, wie in NIST FIPS 204, Abschnitt 6.2 definiert.
AWS KMS hat einen Nachrichtentyp, der EXTERNAL_MU
für Nachrichten mit mehr als 4 KB aufgerufen wird. Wenn Sie diesen anstelle des RAW
Nachrichtentyps verwenden, gilt Folgendes AWS KMS:
-
Geht davon aus, dass Sie den Hashing-Schritt bereits ausgeführt haben
-
Überspringt den internen Hashing-Prozess
-
Funktioniert mit Nachrichten beliebiger Größe
Wenn Sie eine Nachricht verifizieren, hängt die verwendete Methode von der Größenbeschränkung des externen Systems oder der Bibliothek ab und davon, ob sie den 64-Byte-Nachrichtenrepräsentanten μ unterstützt:
-
Wenn die Nachricht kleiner als die Größenbeschränkung ist, verwenden Sie den
RAW
Nachrichtentyp. -
Wenn die Nachricht die Größenbeschränkung überschreitet, verwenden Sie den repräsentativen Wert μ im externen System.
In den folgenden Abschnitten wird gezeigt, wie Nachrichten mit OpenSSL signiert AWS KMS und überprüft werden. Wir bieten Beispiele für Nachrichten, die unter und über der Nachrichtengrößenbeschränkung von AWS KMS 4 KB liegen. OpenSSL legt kein Limit für die Nachrichtengröße zur Überprüfung fest.
Holen Sie sich für beide Beispiele zuerst den öffentlichen Schlüssel von AWS KMS. Verwenden Sie den folgenden AWS CLI -Befehl:
aws kms get-public-key \ --key-id _<1234abcd-12ab-34cd-56ef-1234567890ab>_ \ --output text \ --query PublicKey | base64 --decode > public_key.der
Nachrichtengröße weniger als 4 KB
Verwenden Sie für Nachrichten unter 4 KB den RAW
Nachrichtentyp mit AWS KMS. Sie können dies zwar verwendenEXTERNAL_MU
, für Nachrichten innerhalb der Größenbeschränkung ist dies jedoch nicht erforderlich.
Verwenden Sie den folgenden AWS CLI Befehl, um die Nachricht zu signieren:
aws kms sign \ --key-id _<1234abcd-12ab-34cd-56ef-1234567890ab>_ \ --message '
your message
' \ --message-type RAW \ --signing-algorithm ML_DSA_SHAKE_256 \ --output text \ --query Signature | base64 --decode > ExampleSignature.bin
Verwenden Sie den folgenden Befehl, um diese Nachricht mit OpenSSL zu überprüfen:
echo -n 'your message' | ./openssl dgst -verify public_key.der -signature ExampleSignature.bin
Nachrichtengröße mehr als 4 KB
Verwenden Sie den EXTERNAL_MU
Nachrichtentyp, um Nachrichten zu signieren, die größer als 4 KB sind. Bei der Verwendung EXTERNAL_MU
wird die Nachricht extern an einen 64-Byte-Repräsentanten μ vorgehasht, wie in NIST FIPS 204 Abschnitt 6.2 definiert, und sie an die Signier- oder Verifizierungsvorgänge übergeben. Beachten Sie, dass sich dies von dem in NIST FIPS 204 Abschnitt 5.4 definierten „Pre-Hash MLDSA“ oder HashML-DSA unterscheidet.
-
Konstruieren Sie zunächst ein Nachrichtenpräfix. Das Präfix enthält ein Domänentrennzeichen, die Länge eines beliebigen Kontextes und den Kontext. Die Standardeinstellung für das Domänentrennzeichen und die Kontextlänge ist Null.
-
Stellen Sie der Nachricht das Nachrichtenpräfix voran.
-
Verwenden Sie diese Option SHAKE256 , um den öffentlichen Schlüssel zu hashen und ihn dem Ergebnis von Schritt 2 voranzustellen.
-
Hashen Sie abschließend das Ergebnis von Schritt 3, um ein
EXTERNAL_MU
64-Byte-Ergebnis zu erhalten.
Das folgende Beispiel verwendet OpenSSL 3.5, um das EXTERNAL_MU
zu erstellen:
{ openssl asn1parse -inform DER -in public_key.der -strparse 17 -noout -out - 2>/dev/null | openssl dgst -provider default -shake256 -xoflen 64 -binary; printf '\x00\x00'; echo -n "your message" } | openssl dgst -provider default -shake256 -xoflen 64 -binary > mu.bin
Nachdem Sie die mu.bin
Datei erstellt haben, rufen Sie die AWS KMS API mit dem folgenden Befehl auf, um die Nachricht zu signieren:
aws kms sign \ --key-id _<1234abcd-12ab-34cd-56ef-1234567890ab>_ \ --message fileb://mu.bin \ --message-type EXTERNAL_MU \ --signing-algorithm ML_DSA_SHAKE_256 \ --output text \ --query Signature | base64 --decode > ExampleSignature.bin
Die resultierende Signatur entspricht der RAW
Signatur der Originalnachricht. Sie können denselben OpenSSL 3.5-Befehl verwenden, um die Nachricht zu überprüfen:
echo -n 'your message' | ./openssl dgst -verify public_key.der -signature ExampleSignature.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 0009-2012 definiert wurde. GM/T 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 Castle
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-VersionenSM2OfflineOperationHelper
-Klasse mit Bibliotheken, wie Bouncy Castle
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. DiecalculateSM2Digest
Methode generiert einen Nachrichtenüberblick mit dem SM3 Hashing-Algorithmus. 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 denDEFAULT_DISTINGUISHING_ID
-Wert ändern.
-
- Verify
-
Um eine Signatur offline zu prüfen, verwenden Sie die
offlineSM2DSAVerify
-Methode. DieofflineSM2DSAVerify
-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. DieofflineSM2PKEEncrypt
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"); } }