如何使用KMS加密保护线下数据 解密本地文件 步骤1 请准备基础认证信息。 ACCESSKEY: 帐号Access Key SECRETACCESSKEY: 帐号Secret Access Key PROJECTID: 项目ID KMSENDPOINT: KMS服务访问终端地址。 步骤2 解密本地文件。 示例代码中: 用户主密钥:控制台创建的密钥ID。 输出的密文数据文件:SecondEncryptFile.jpg。 加密后再解密的数据文件:ThirdDecryptFile.jpg。 import com.ctyun.sdk.core.auth.BasicCredentials; import com.ctyun.sdk.kms.v1.KmsClient; import com.ctyun.sdk.kms.v1.model.CreateDatakeyRequest; import com.ctyun.sdk.kms.v1.model.CreateDatakeyRequestBody; import com.ctyun.sdk.kms.v1.model.CreateDatakeyResponse; import com.ctyun.sdk.kms.v1.model.DecryptDatakeyRequest; import com.ctyun.sdk.kms.v1.model.DecryptDatakeyRequestBody; import javax.crypto.Cipher; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Files; import java.security.SecureRandom; / 使用数据密钥(DEK)进行文件加解密 激活assert语法,请在VMOPTIONS中添加ea / public class FileStreamEncryptionExample { private static final String ACCESSKEY " "; private static final String SECRETACCESSKEY " "; private static final String PROJECTID " "; private static final String KMSENDPOINT " "; // KMS服务接口版本信息,当前固定为v1.0 private static final String KMSINTERFACEVERSION "v1.0"; / AES算法相关标识: AESKEYBITLENGTH: AES256密钥比特长度 AESKEYBYTELENGTH: AES256密钥字节长度 AESALG: AES256算法,本例分组模式使用GCM,填充使用PKCS5Padding AESFLAG: AES算法标识 GCMTAGLENGTH: GCM TAG长度 GCMIVLENGTH: GCM 初始向量长度 / private static final String AESKEYBITLENGTH "256"; private static final String AESKEYBYTELENGTH "32"; private static final String AESALG "AES/GCM/PKCS5Padding"; private static final String AESFLAG "AES"; private static final int GCMTAGLENGTH 16; private static final int GCMIVLENGTH 12; public static void main(final String[] args) { // 您在控制台创建的用户主密钥ID final String keyId args[0]; // 创建数据密钥时,响应的密文数据密钥 final String cipherText args[1]; decryptFile(keyId, cipherText); } / 使用数据密钥加解密文件实例 @param keyId 用户主密钥ID @param cipherText 密文数据密钥 / static void decryptFile(String keyId,String cipherText) { // 1.准备访问认证信息 final BasicCredentials auth new BasicCredentials().withAk(ACCESSKEY).withSk(SECRETACCESSKEY) .withProjectId(PROJECTID); // 2.初始化SDK,传入认证信息及KMS访问终端地址 final KmsClient kmsClient KmsClient.newBuilder().withCredential(auth).withEndpoint(KMSENDPOINT).build(); // 3.准备待加密的文件 // inFile 待加密的文件 // outEncryptFile 加密后的文件 // outDecryptFile 加密后再解密的文件 final File inFile new File("FirstPlainFile.jpg"); final File outEncryptFile new File("SecondEncryptFile.jpg"); final File outDecryptFile new File("ThirdDecryptFile.jpg"); // 4.使用AES算法进行解密时,初始向量需要与加密时保持一致,此处仅为占位。 final byte[] iv new byte[GCMIVLENGTH]; // 5.组装解密数据密钥的请求,其中cipherText为创建数据密钥时返回的密文数据密钥。 final DecryptDatakeyRequest decryptDatakeyRequest new DecryptDatakeyRequest() .withVersionId(KMSINTERFACEVERSION).withBody(new DecryptDatakeyRequestBody() .withKeyId(keyId).withCipherText(cipherText).withDatakeyCipherLength(AESKEYBYTELENGTH)); // 6.解密数据密钥,并对返回的16进制明文密钥换成byte数组 final byte[] decryptDataKey hexToBytes(kmsClient.decryptDatakey(decryptDatakeyRequest).getDataKey()); // 7.对文件进行解密,并存储解密后的文件 // 句末的iv为加密示例中创建的初始向量 doFileFinal(Cipher.DECRYPTMODE, outEncryptFile, outDecryptFile, decryptDataKey, iv); // 8.比对原文件和加密后再解密的文件 assert getFileSha256Sum(inFile).equals(getFileSha256Sum(outDecryptFile)); } / 对文件进行加解密 @param cipherMode 加密模式,可选值为Cipher.ENCRYPTMODE或者Cipher.DECRYPTMODE @param infile 待加解密的文件 @param outFile 加解密后的文件 @param keyPlain 明文密钥 @param iv 初始化向量 / static void doFileFinal(int cipherMode, File infile, File outFile, byte[] keyPlain, byte[] iv) { try (BufferedInputStream bis new BufferedInputStream(new FileInputStream(infile)); BufferedOutputStream bos new BufferedOutputStream(new FileOutputStream(outFile))) { final byte[] bytIn new byte[(int) infile.length()]; final int fileLength bis.read(bytIn); assert fileLength > 0; final SecretKeySpec secretKeySpec new SecretKeySpec(keyPlain, AESFLAG); final Cipher cipher Cipher.getInstance(AESALG); final GCMParameterSpec gcmParameterSpec new GCMParameterSpec(GCMTAGLENGTH Byte.SIZE, iv); cipher.init(cipherMode, secretKeySpec, gcmParameterSpec); final byte[] bytOut cipher.doFinal(bytIn); bos.write(bytOut); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } } / 十六进制字符串转byte数组 @param hexString 十六进制字符串 @return byte数组 / static byte[] hexToBytes(String hexString) { final int stringLength hexString.length(); assert stringLength > 0; final byte[] result new byte[stringLength / 2]; int j 0; for (int i 0; i < stringLength; i + 2) { result[j++] (byte) Integer.parseInt(hexString.substring(i, i + 2), 16); } return result; } / 计算文件SHA256摘要 @param file 文件 @return SHA256摘要 / static String getFileSha256Sum(File file) { int length; MessageDigest sha256; byte[] buffer new byte[1024]; try { sha256 MessageDigest.getInstance("SHA256"); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e.getMessage()); } try (FileInputStream inputStream new FileInputStream(file)) { while ((length inputStream.read(buffer)) ! 1) { sha256.update(buffer, 0, length); } return new BigInteger(1, sha256.digest()).toString(16); } catch (IOException e) { throw new RuntimeException(e.getMessage()); } } }