从 cert 文件中获取 Secret Key 以用于 AES 算法进行加密和解密
Posted
技术标签:
【中文标题】从 cert 文件中获取 Secret Key 以用于 AES 算法进行加密和解密【英文标题】:Obtaining Secret Key from cert file to use in AES algorithm for encryption and decryption 【发布时间】:2018-06-30 19:15:54 【问题描述】:我正在进行 AES 加密,其中我将使用来自 cert 文件的密钥来初始化密码,如下所示。
encryptModeCipher = Cipher.getInstance("AES"); encryptModeCipher.init(Cipher.ENCRYPT_MODE, aesSecretKey);
但我在这里看到的问题是,我的 secretKey () 对于我使用的所有证书都保持不变。任何建议为什么?并提出一个好主意。
byte[] encryptionKey = Arrays.copyOf(encoded, 32); secretKey = new SecretKeySpec(encryptionKey, algorithm);
公共类 AESEncryptionServiceHelper
private String algorithm = "AES";
private String certPass;
private SecretKey secretKey;
public SecretKey setKey()
try
certPass="****";
char[] pass = certPass.toCharArray();
KeyStore keyStore = KeyStore.getInstance("jceks");
File file = new File("D:/aws-kms-dps/***.jks");
InputStream inputStream = new FileInputStream(file);
keyStore.load(inputStream, pass);
Certificate cert = keyStore.getCertificate("****");
Key key = cert.getPublicKey();
secretKey = new SecretKeySpec(key.getEncoded(), algorithm);
byte[] encoded = secretKey.getEncoded();
byte[] encryptionKey = Arrays.copyOf(encoded, 32);
secretKey = new SecretKeySpec(encryptionKey, algorithm);
catch (IOException e)
System.out.println(e);
catch (Exception e)
System.out.println(e);
return secretKey;
public static void main(String args[])
AESEncryptionServiceHelper aesEncryptionServiceHelper=new AESEncryptionServiceHelper();
aesEncryptionServiceHelper.setKey();
【问题讨论】:
证书文件中没有密钥。根据定义,其中的所有内容都是公开的,包括您从中构建所谓的“秘密密钥”的公钥。如果您使用公钥作为密钥,那么您已经处于完全不安全的状态。不清楚你在问什么,甚至在说什么。 是的。我对此不太清楚......我只能从证书中获取一个公钥......但不知何故我需要从中生成一个秘密密钥......建议我一个好方法 不,您不需要这样做,因为它不安全。你不需要做错事。可能你误解了你的要求。发回以澄清。 【参考方案1】:您似乎正在使用(部分)公钥作为 AES 密钥。这是一个非常糟糕的主意,因为
公钥是 .. 好 .. 公开的和静态的 它的熵相对较低(因为在 ASN.1 格式中定义了多个字节)您是否研究过如何正确使用 PKI 进行加密,或者您只是在猜测/使用加密 API?
假设您想使用公钥和 AES(称为hybrid encryption)进行加密,您可以以my blog 为例
请阅读并理解(或任何其他关于密码学的优秀博客),您似乎缺少使用 IV(盐)和 MAC
// generate random AES key
KeyGenerator keyGenerator = KeyGenerator.getInstance(SYMMETRIC_KEY_ALG);
SecretKey symmetricKey = keyGenerator.generateKey();
// this assumes there's whole keypair (including private key)
// normally only a certificate with PubKey is available
PublicKey pubKey = keystoreEntry.getCertificate().getPublicKey();
params.setKey(symmetricKey.getEncoded());
// execute symmetric encryption
this.symmetricEncryption(params);
// encrypt the key with the public key
Cipher cipher = Cipher.getInstance(PKI_CIPHER_ALG);
cipher.init(Cipher.WRAP_MODE, pubKey);
byte[] wrappedKey = cipher.wrap(symmetricKey);
LOGGER.log(Level.INFO, "Wrapped key: 0", Base64.getEncoder().encodeToString(wrappedKey));
params.setKey(wrappedKey);
对称加密本身可以如下实现
// initialization vector
SecureRandom rnd = new SecureRandom();
byte[] iv = new byte[SYMMETRIC_BLOCK_SIZE / 8];
rnd.nextBytes(iv);
encryptionParams.setIv(iv);
IvParameterSpec ivParamSpec = new IvParameterSpec(iv);
SecretKey symmetricKey = new SecretKeySpec(encryptionParams.getKey(), SYMMETRIC_KEY_ALG);
Cipher cipher = Cipher.getInstance(SYMMETRIC_CIPHER_NAME);
cipher.init(Cipher.ENCRYPT_MODE, symmetricKey, ivParamSpec);
// for HMAC we should be able to use the same key as for encryption
// for CBC-MAC it may not be the case
// https://en.wikipedia.org/wiki/CBC-MAC#Using_the_same_key_for_encryption_and_authentication
Mac mac = Mac.getInstance(EncryptionTest.HASH_ALGORITHM_NAME);
mac.init(symmetricKey);
byte[] encrypted = cipher.doFinal(encryptionParams.getPlaintext());
encryptionParams.setCiphertext(encrypted);
byte[] authTag = mac.doFinal(encrypted);
encryptionParams.setMac(authTag);
【讨论】:
以上是关于从 cert 文件中获取 Secret Key 以用于 AES 算法进行加密和解密的主要内容,如果未能解决你的问题,请参考以下文章
带有 laravel 的 Paypal sdk - 从 env 文件中获取 Client_id/secret
使用stringIO对象作为ssl key / cert文件
如何解决 Secret tls-cert.default 未知问题?