Java용 AWS 암호화 SDK 예제 코드 - AWS 암호화 SDK

문서의 영문과 번역 사이에 충돌이 있는 경우에는 영문 버전을 따릅니다. 번역 버전은 기계 번역을 사용하여 제공합니다.

Java용 AWS 암호화 SDK 예제 코드

다음 예제에서는 Java용 AWS 암호화 SDK를 사용하여 데이터를 암호화 및 암호화 해제하는 방법을 보여줍니다.

문자열 암호화 및 해독

다음 예제에서는 Java용 AWS 암호화 SDK를 사용하여 문자열을 암호화 및 해독하는 방법을 보여줍니다. 문자열을 사용하기 전에 바이트 배열로 변환하십시오.

이 예에서는 AWS Key Management Service(AWS KMS) 고객 마스터 키(CMK)를 마스터 키로 사용합니다. 키 생성에 대한 도움말은 다음을 참조하십시오. 키 만들기 에서 AWS Key Management Service Developer Guide.

encryptData() 메서드를 호출하면 암호문, 암호화된 데이터 키 및 암호화 컨텍스트를 포함하는 암호화된 메시지(CryptoResult)가 반환됩니다. CryptoResult 객체에서 getResult를 호출하면 decryptData() 메서드로 전달할 수 있는 암호화된 메시지의 base-64로 인코딩된 문자열 버전을 반환합니다.

마찬가지로 decryptData()를 호출하면 반환되는 CryptoResult 객체에는 일반 텍스트 메시지와 CMK ID가 포함됩니다. 애플리케이션이 일반 텍스트를 반환하기 전에 암호화된 메시지의 CMK ID 및 암호화 컨텍스트가 예상한 것인지 확인하십시오.

/* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except * in compliance with the License. A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ package com.amazonaws.crypto.examples; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collections; import java.util.Map; import com.amazonaws.encryptionsdk.AwsCrypto; import com.amazonaws.encryptionsdk.CryptoResult; import com.amazonaws.encryptionsdk.kms.KmsMasterKey; import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider; /** * <p> * Encrypts and then decrypts data using an AWS KMS customer master key. * * <p> * Arguments: * <ol> * <li>Key ARN: For help finding the Amazon Resource Name (ARN) of your AWS KMS customer master * key (CMK), see 'Viewing Keys' at http://docs.aws.amazon.com/kms/latest/developerguide/viewing-keys.html * </ol> */ public class BasicEncryptionExample { private static final byte[] EXAMPLE_DATA = "Hello World".getBytes(StandardCharsets.UTF_8); public static void main(final String[] args) { final String keyArn = args[0]; encryptAndDecrypt(keyArn); } static void encryptAndDecrypt(final String keyArn) { // 1. Instantiate the SDK final AwsCrypto crypto = new AwsCrypto(); // 2. Instantiate a KMS master key provider final KmsMasterKeyProvider masterKeyProvider = KmsMasterKeyProvider.builder().withKeysForEncryption(keyArn).build(); // 3. Create an encryption context // // Most encrypted data should have an associated encryption context // to protect integrity. This sample uses placeholder values. // // For more information see: // blogs.aws.amazon.com/security/post/Tx2LZ6WBJJANTNW/How-to-Protect-the-Integrity-of-Your-Encrypted-Data-by-Using-AWS-Key-Management final Map<String, String> encryptionContext = Collections.singletonMap("ExampleContextKey", "ExampleContextValue"); // 4. Encrypt the data final CryptoResult<byte[], KmsMasterKey> encryptResult = crypto.encryptData(masterKeyProvider, EXAMPLE_DATA, encryptionContext); final byte[] ciphertext = encryptResult.getResult(); // 5. Decrypt the data final CryptoResult<byte[], KmsMasterKey> decryptResult = crypto.decryptData(masterKeyProvider, ciphertext); // 6. Before verifying the plaintext, verify that the customer master key that // was used in the encryption operation was the one supplied to the master key provider. if (!decryptResult.getMasterKeyIds().get(0).equals(keyArn)) { throw new IllegalStateException("Wrong key ID!"); } // 7. Also, verify that the encryption context in the result contains the // encryption context supplied to the encryptData method. Because the // SDK can add values to the encryption context, don't require that // the entire context matches. if (!encryptionContext.entrySet().stream() .allMatch(e -> e.getValue().equals(decryptResult.getEncryptionContext().get(e.getKey())))) { throw new IllegalStateException("Wrong Encryption Context!"); } // 8. Verify that the decrypted plaintext matches the original plaintext assert Arrays.equals(decryptResult.getResult(), EXAMPLE_DATA); } }

바이트 스트림 암호화 및 해독

다음 예제에서는 AWS 암호화 SDK를 사용하여 바이트 스트림을 암호화 및 해독하는 방법을 보여줍니다. 이 예제에서는 AWS. Java Cryptography Extension(JCE)을 사용하여 마스터 키를 보호합니다.

/* * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except * in compliance with the License. A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ package com.amazonaws.crypto.examples; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.security.SecureRandom; import java.util.Collections; import java.util.Map; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import com.amazonaws.encryptionsdk.AwsCrypto; import com.amazonaws.encryptionsdk.CryptoInputStream; import com.amazonaws.encryptionsdk.MasterKey; import com.amazonaws.encryptionsdk.jce.JceMasterKey; import com.amazonaws.util.IOUtils; /** * <p> * Encrypts and then decrypts a file under a random key * * <p> * Arguments: * <ol> * <li>Name of file containing plaintext data to encrypt * </ol> * * <p> * This program demonstrates using a standard Java {@link SecretKey} object as a {@link MasterKey} to * encrypt and decrypt streaming data. */ public class FileStreamingExample { private static String srcFile; public static void main(String[] args) throws IOException { srcFile = args[0]; // In this example, we generate a random key. In practice, // you would get a key from an existing store. SecretKey cryptoKey = retrieveEncryptionKey(); // Create a JCE master key provider using the random key and an AES-GCM encryption algorithm JceMasterKey masterKey = JceMasterKey.getInstance(cryptoKey, "Example", "RandomKey", "AES/GCM/NoPadding"); // Instantiate the SDK AwsCrypto crypto = new AwsCrypto(); // Create an encryption context to identify this ciphertext Map<String, String> context = Collections.singletonMap("Example", "FileStreaming"); // Because the file might be too large to load into memory, we stream the data, instead of //loading it all at once. FileInputStream in = new FileInputStream(srcFile); CryptoInputStream<JceMasterKey> encryptingStream = crypto.createEncryptingStream(masterKey, in, context); FileOutputStream out = new FileOutputStream(srcFile + ".encrypted"); IOUtils.copy(encryptingStream, out); encryptingStream.close(); out.close(); // Decrypt the file. Verify the encryption context before returning the plaintext. in = new FileInputStream(srcFile + ".encrypted"); CryptoInputStream<JceMasterKey> decryptingStream = crypto.createDecryptingStream(masterKey, in); // Does it contain the expected encryption context? if (!"FileStreaming".equals(decryptingStream.getCryptoResult().getEncryptionContext().get("Example"))) { throw new IllegalStateException("Bad encryption context"); } // Return the plaintext data out = new FileOutputStream(srcFile + ".decrypted"); IOUtils.copy(decryptingStream, out); decryptingStream.close(); out.close(); } /** * In practice, this key would be saved in a secure location. * For this demo, we generate a new random key for each operation. */ private static SecretKey retrieveEncryptionKey() { SecureRandom rnd = new SecureRandom(); byte[] rawKey = new byte[16]; // 128 bits rnd.nextBytes(rawKey); return new SecretKeySpec(rawKey, "AES"); } }

여러 마스터 키 공급자로 바이트 스트림 암호화 및 해독

다음 예제에서는 두 개 이상의 마스터 키 공급자와 함께 AWS 암호화 SDK를 사용하는 방법을 보여줍니다. 둘 이상의 마스터 키 공급자를 사용하면 하나의 마스터 키 공급자를 해독에 사용할 수 없는 경우 중복성이 생성됩니다. 이 예에서는 AWS KMS의 CMK 및 RSA 키 페어를 마스터 키로 사용합니다.

/* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except * in compliance with the License. A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ package com.amazonaws.crypto.examples; import java.io.FileInputStream; import java.io.FileOutputStream; import java.security.GeneralSecurityException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import com.amazonaws.encryptionsdk.AwsCrypto; import com.amazonaws.encryptionsdk.CryptoOutputStream; import com.amazonaws.encryptionsdk.MasterKeyProvider; import com.amazonaws.encryptionsdk.jce.JceMasterKey; import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider; import com.amazonaws.encryptionsdk.multi.MultipleProviderFactory; import com.amazonaws.util.IOUtils; /** * <p> * Encrypts a file using both KMS and an asymmetric key pair. * * <p> * Arguments: * <ol> * <li>Key ARN: For help finding the Amazon Resource Name (ARN) of your KMS customer master * key (CMK), see 'Viewing Keys' at http://docs.aws.amazon.com/kms/latest/developerguide/viewing-keys.html * <li>Name of file containing plaintext data to encrypt * </ol> * * You might use AWS Key Management Service (KMS) for most encryption and decryption operations, but * still want the option of decrypting your data offline independently of KMS. This sample * demonstrates one way to do this. * * The sample encrypts data under both a KMS customer master key (CMK) and an "escrowed" RSA key pair * so that either key alone can decrypt it. You might commonly use the KMS CMK for decryption. However, * at any time, you can use the private RSA key to decrypt the ciphertext independent of KMS. * * This sample uses the JCEMasterKey class to generate a RSA public-private key pair * and saves the key pair in memory. In practice, you would store the private key in a secure offline * location, such as an offline HSM, and distribute the public key to your development team. * */ public class EscrowedEncryptExample { private static PublicKey publicEscrowKey; private static PrivateKey privateEscrowKey; public static void main(final String[] args) throws Exception { // This sample generates a new random key for each operation. // In practice, you would distribute the public key and save the private key in secure // storage. generateEscrowKeyPair(); final String kmsArn = args[0]; final String fileName = args[1]; standardEncrypt(kmsArn, fileName); standardDecrypt(kmsArn, fileName); escrowDecrypt(fileName); } private static void standardEncrypt(final String kmsArn, final String fileName) throws Exception { // Encrypt with the KMS CMK and the escrowed public key // 1. Instantiate the SDK final AwsCrypto crypto = new AwsCrypto(); // 2. Instantiate a KMS master key provider final KmsMasterKeyProvider kms = KmsMasterKeyProvider.builder().withKeysForEncryption(kmsArn).build(); // 3. Instantiate a JCE master key provider // Because the user does not have access to the private escrow key, // they pass in "null" for the private key parameter. final JceMasterKey escrowPub = JceMasterKey.getInstance(publicEscrowKey, null, "Escrow", "Escrow", "RSA/ECB/OAEPWithSHA-512AndMGF1Padding"); // 4. Combine the providers into a single master key provider final MasterKeyProvider<?> provider = MultipleProviderFactory.buildMultiProvider(kms, escrowPub); // 5. Encrypt the file // To simplify the code, we omit the encryption context. Production code should always // use an encryption context. For an example, see the other SDK samples. final FileInputStream in = new FileInputStream(fileName); final FileOutputStream out = new FileOutputStream(fileName + ".encrypted"); final CryptoOutputStream<?> encryptingStream = crypto.createEncryptingStream(provider, out); IOUtils.copy(in, encryptingStream); in.close(); encryptingStream.close(); } private static void standardDecrypt(final String kmsArn, final String fileName) throws Exception { // Decrypt with the KMS CMK and the escrow public key. You can use a combined provider, // as shown here, or just the KMS master key provider. // 1. Instantiate the SDK final AwsCrypto crypto = new AwsCrypto(); // 2. Instantiate a KMS master key provider final KmsMasterKeyProvider kms = KmsMasterKeyProvider.builder().withKeysForEncryption(kmsArn).build(); // 3. Instantiate a JCE master key provider // Because the user does not have access to the private escrow // key, they pass in "null" for the private key parameter. final JceMasterKey escrowPub = JceMasterKey.getInstance(publicEscrowKey, null, "Escrow", "Escrow", "RSA/ECB/OAEPWithSHA-512AndMGF1Padding"); // 4. Combine the providers into a single master key provider final MasterKeyProvider<?> provider = MultipleProviderFactory.buildMultiProvider(kms, escrowPub); // 5. Decrypt the file // To simplify the code, we omit the encryption context. Production code should always // use an encryption context. For an example, see the other SDK samples. final FileInputStream in = new FileInputStream(fileName + ".encrypted"); final FileOutputStream out = new FileOutputStream(fileName + ".decrypted"); final CryptoOutputStream<?> decryptingStream = crypto.createDecryptingStream(provider, out); IOUtils.copy(in, decryptingStream); in.close(); decryptingStream.close(); } private static void escrowDecrypt(final String fileName) throws Exception { // You can decrypt the stream using only the private key. // This method does not call KMS. // 1. Instantiate the SDK final AwsCrypto crypto = new AwsCrypto(); // 2. Instantiate a JCE master key // This method call uses the escrowed private key, not null final JceMasterKey escrowPriv = JceMasterKey.getInstance(publicEscrowKey, privateEscrowKey, "Escrow", "Escrow", "RSA/ECB/OAEPWithSHA-512AndMGF1Padding"); // 3. Decrypt the file // To simplify the code, we omit the encryption context. Production code should always // use an encryption context. For an example, see the other SDK samples. final FileInputStream in = new FileInputStream(fileName + ".encrypted"); final FileOutputStream out = new FileOutputStream(fileName + ".deescrowed"); final CryptoOutputStream<?> decryptingStream = crypto.createDecryptingStream(escrowPriv, out); IOUtils.copy(in, decryptingStream); in.close(); decryptingStream.close(); } private static void generateEscrowKeyPair() throws GeneralSecurityException { final KeyPairGenerator kg = KeyPairGenerator.getInstance("RSA"); kg.initialize(4096); // Escrow keys should be very strong final KeyPair keyPair = kg.generateKeyPair(); publicEscrowKey = keyPair.getPublic(); privateEscrowKey = keyPair.getPrivate(); } }