Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.
Contoh operasi offline
Setelah mengunduh kunci publik dari key pair KMS asimetris Anda, Anda dapat membagikannya dengan orang lain dan menggunakannya untuk melakukan operasi offline.
AWS CloudTrail log yang mencatat setiap AWS KMS operasi, termasuk permintaan, tanggapan, tanggal, waktu, dan pengguna yang berwenang, tidak mencatat penggunaan kunci publik di luar AWS KMS.
Topik ini memberikan contoh operasi offline dan detail yang AWS KMS disediakan alat untuk membuat operasi offline lebih mudah.
Topik
Menurunkan rahasia bersama secara offline
Anda dapat mengunduh kunci publik dari key pair ECC Anda untuk digunakan dalam operasi offline, yaitu operasi di luar. AWS KMS
Panduan OpenSSL
-
Buat key pair ECC di OpenSSL dan persiapkan untuk digunakan. 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"`
-
Buat key pair perjanjian kunci ECC AWS KMS dan persiapkan untuk digunakan dengan 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}
-
Turunkan shared secret di OpenSSL menggunakan private key di OpenSSL dan public KMS key.
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}
Verifikasi offline dengan pasangan kunci ML-DSA
AWS KMS mendukung varian lindung nilai penandatanganan ML-DSA, seperti yang dijelaskan dalam Standar Pemrosesan Informasi Federal (FIPS) 204 bagian standar 3.4
Untuk menandatangani pesan yang lebih besar dari 4 KB, Anda melakukan langkah pra-pemrosesan pesan di luar. AWS KMS Langkah hashing ini menciptakan perwakilan pesan 64-byte μ, seperti yang didefinisikan dalam NIST FIPS 204, bagian 6.2.
AWS KMS memiliki jenis pesan yang dipanggil EXTERNAL_MU
untuk pesan yang lebih besar dari 4 KB. Saat Anda menggunakan ini alih-alih jenis RAW
pesan, AWS KMS:
-
Asumsikan Anda telah melakukan langkah hashing
-
Melewatkan proses hashing internalnya
-
Bekerja dengan pesan dari berbagai ukuran
Saat Anda memverifikasi pesan, metode yang Anda gunakan bergantung pada batasan ukuran sistem eksternal atau pustaka dan apakah itu mendukung perwakilan pesan 64-byte μ:
-
Jika pesan lebih kecil dari batasan ukuran, gunakan jenis
RAW
pesan. -
Jika pesan lebih besar dari batasan ukuran, gunakan representatif μ di sistem eksternal.
Bagian berikut menunjukkan cara menandatangani pesan menggunakan AWS KMS dan memverifikasi pesan menggunakan OpenSSL. Kami memberikan contoh untuk pesan di bawah dan di atas batas ukuran pesan 4 KB yang diberlakukan oleh AWS KMS. OpenSSL tidak memberlakukan batasan ukuran pesan untuk verifikasi.
Untuk kedua contoh, pertama-tama dapatkan kunci publik dari AWS KMS. Gunakan perintah AWS CLI berikut:
aws kms get-public-key \ --key-id _<1234abcd-12ab-34cd-56ef-1234567890ab>_ \ --output text \ --query PublicKey | base64 --decode > public_key.der
Ukuran pesan kurang dari 4KB
Untuk pesan di bawah 4 KB, gunakan jenis RAW
pesan dengan AWS KMS. Meskipun Anda dapat menggunakanEXTERNAL_MU
, tidak perlu untuk pesan dalam batas ukuran.
Gunakan AWS CLI perintah berikut untuk menandatangani pesan:
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
Untuk memverifikasi pesan ini menggunakan OpenSSL gunakan perintah berikut:
echo -n 'your message' | ./openssl dgst -verify public_key.der -signature ExampleSignature.bin
Ukuran pesan lebih dari 4KB
Untuk menandatangani pesan yang lebih besar dari 4KB, gunakan jenis EXTERNAL_MU
pesan. Saat Anda menggunakanEXTERNAL_MU
, Anda melakukan pra-hash pesan secara eksternal ke perwakilan 64-byte μ seperti yang didefinisikan dalam NIST FIPS 204 bagian 6.2 dan meneruskannya ke operasi penandatanganan atau verifikasi. Perhatikan bahwa ini berbeda dari “Pra-hash MLDSA” atau HashML-DSA yang didefinisikan dalam NIST FIPS 204 bagian 5.4.
-
Pertama, buat awalan pesan. Awalan berisi pemisah domain, panjang konteks apa pun, dan konteksnya. Default untuk pemisah domain dan panjang konteks adalah nol.
-
Tambahkan awalan pesan ke pesan.
-
Gunakan SHAKE256 untuk hash kunci publik dan menutupinya ke hasil langkah 2.
-
Akhirnya, hash hasil langkah 3 untuk menghasilkan
EXTERNAL_MU
64-byte.
Contoh berikut menggunakan OpenSSL 3.5 untuk membangun: EXTERNAL_MU
{ 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
Setelah Anda membuat mu.bin
file, panggil AWS KMS API dengan perintah berikut untuk menandatangani pesan:
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
Tanda tangan yang dihasilkan sama dengan RAW
tanda tangan pada pesan asli. Anda dapat menggunakan perintah OpenSSL 3.5 yang sama untuk memverifikasi pesan:
echo -n 'your message' | ./openssl dgst -verify public_key.der -signature ExampleSignature.bin
Verifikasi offline dengan pasangan SM2 kunci (hanya Wilayah Tiongkok)
Untuk memverifikasi tanda tangan di luar AWS KMS dengan kunci SM2 publik, Anda harus menentukan ID pembeda. Saat Anda meneruskan pesan mentah, ke Sign API MessageType:RAW
, AWS KMS menggunakan ID pembeda default, yang ditentukan oleh OSCCA di 0009-2012. 1234567812345678
GM/T Anda tidak dapat menentukan ID pembeda Anda sendiri di dalamnya AWS KMS.
Namun, jika Anda membuat intisari pesan di luar AWS, Anda dapat menentukan ID pembeda Anda sendiri, lalu meneruskan intisari pesan MessageType:DIGEST
, untuk AWS KMS menandatangani. Untuk melakukan ini, ubah DEFAULT_DISTINGUISHING_ID
nilai di SM2OfflineOperationHelper
kelas. ID pembeda yang Anda tentukan dapat berupa string apa pun hingga 8,192 karakter. Setelah AWS KMS menandatangani intisari pesan, Anda memerlukan intisari pesan atau pesan dan ID pembeda yang digunakan untuk menghitung intisari untuk memverifikasinya secara offline.
penting
Kode SM2OfflineOperationHelper
referensi dirancang agar kompatibel dengan Bouncy Castle
SM2OfflineOperationHelper
kelas
Untuk membantu Anda dengan operasi offline dengan SM2 kunci, SM2OfflineOperationHelper
kelas untuk Java memiliki metode yang melakukan tugas untuk Anda. Anda dapat menggunakan kelas pembantu ini sebagai model untuk penyedia kriptografi lainnya.
Di dalamnya AWS KMS, konversi ciphertext mentah dan perhitungan intisari pesan SM2 DSA terjadi secara otomatis. Tidak semua penyedia kriptografi menerapkan dengan SM2 cara yang sama. Beberapa pustaka, seperti OpenSSLSM2OfflineOperationHelper
kelas berikut dengan pustaka, seperti Bouncy Castle
SM2OfflineOperationHelper
Kelas menyediakan metode untuk operasi offline berikut:
-
- Perhitungan intisari pesan
-
Untuk menghasilkan intisari pesan secara offline yang dapat Anda gunakan untuk verifikasi offline, atau yang dapat diteruskan AWS KMS ke tanda tangan, gunakan
calculateSM2Digest
metode ini.calculateSM2Digest
Metode ini menghasilkan intisari pesan dengan algoritma SM3 hashing. GetPublicKeyAPI mengembalikan kunci publik Anda dalam format biner. Anda harus mengurai kunci biner menjadi Java PublicKey. Berikan kunci publik yang diurai dengan pesan. Metode ini secara otomatis menggabungkan pesan Anda dengan ID pembeda default1234567812345678
, tetapi Anda dapat mengatur ID pembeda Anda sendiri dengan mengubah nilainya.DEFAULT_DISTINGUISHING_ID
-
- Verifikasi
-
Untuk memverifikasi tanda tangan secara offline, gunakan
offlineSM2DSAVerify
metode ini.offlineSM2DSAVerify
Metode ini menggunakan intisari pesan yang dihitung dari ID pembeda yang ditentukan, dan pesan asli yang Anda berikan untuk memverifikasi tanda tangan digital. GetPublicKeyAPI mengembalikan kunci publik Anda dalam format biner. Anda harus mengurai kunci biner menjadi Java PublicKey. Berikan kunci publik yang diuraikan dengan pesan asli dan tanda tangan yang ingin Anda verifikasi. Untuk detail selengkapnya, lihat Verifikasi offline dengan pasangan SM2 kunci.
-
- Enkripsi
-
Untuk mengenkripsi plaintext offline, gunakan metode ini.
offlineSM2PKEEncrypt
Metode ini memastikan ciphertext dalam format AWS KMS dapat mendekripsi.offlineSM2PKEEncrypt
Metode mengenkripsi plaintext, dan kemudian mengonversi ciphertext mentah yang dihasilkan oleh PKE ke format ASN.1. SM2 GetPublicKeyAPI mengembalikan kunci publik Anda dalam format biner. Anda harus mengurai kunci biner menjadi Java PublicKey. Berikan kunci publik yang diurai dengan plaintext yang ingin Anda enkripsi.Jika Anda tidak yakin apakah Anda perlu melakukan konversi, gunakan operasi OpenSSL berikut untuk menguji format ciphertext Anda. Jika operasi gagal, Anda perlu mengonversi ciphertext ke format ASN.1.
openssl asn1parse -inform DER -in
ciphertext.der
Secara default, SM2OfflineOperationHelper
kelas menggunakan ID pembeda default1234567812345678
, saat menghasilkan intisari pesan untuk operasi SM2 DSA.
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"); } }