使用 Java 的非对称文件加密
Asymmetric File encryption with Java
我有一个包含 public 密钥和私钥的 pfx 文件,我想使用这些密钥在我的机器上本地加密和解密文件。
那是我的代码:
public static void encryptFile(File file, PublicKey key,
String transformation) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException, IOException,
InvalidAlgorithmParameterException, NoSuchProviderException {
Cipher c = Cipher.getInstance(transformation, "SunJCE");
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyb, "AES");
c.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivspec);
FileInputStream is = new FileInputStream(file);
CipherOutputStream os = new CipherOutputStream(new FileOutputStream(
new File(file.getName() + "_enc")), c);
copy(is, os);
}
public static void decryptFile(File encryptedFile, File decryptedFile,
Key privateKey, String transformation) {
try {
Cipher c = Cipher.getInstance(transformation, "SunJCE");
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
byte[] keyb = privateKey.getEncoded();
SecretKeySpec secretKeySpec = new SecretKeySpec(keyb, "AES");
c.init(Cipher.DECRYPT_MODE, secretKeySpec, ivspec);
CipherInputStream is = new CipherInputStream(new FileInputStream(
encryptedFile), c);
FileOutputStream os = new FileOutputStream(decryptedFile);
copy(is, os);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void copy(InputStream is, OutputStream os) {
try {
byte[] buf = new byte[1024];
long total = 0;
while (true) {
int r = is.read(buf);
if (r == -1) {
break;
}
os.write(buf, 0, r);
total += r;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
is.close();
os.flush();
os.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
我这样称呼它:
CertificateHandler.encryptFile(new File("test.pdf"), pb, "AES/CBC/PKCS5Padding");
CertificateHandler.decryptFile(new File("test.pdf_enc"), new File("test.enc.pdf"), pk, "AES/CBC/NoPadding");
但是我得到这个错误:
java.security.InvalidKeyException: Invalid AES key length: 294 bytes
我使用了 Unlimited JCE Policy 但没有任何改变。当我尝试使用摘要密钥时,我认为它不起作用,因为它被切断了,不再有效
有什么建议吗?
为了正确加密,您遗漏了一些细节。
AES 是一种对称密码,采用密钥大小为 128、192 或 256 位。您不能仅将 RSA 私钥与任何加密方案一起使用。
要使用 RSA 密钥,只需在网上搜索,例如 http://www.java2s.com/Code/Android/Security/RSAencryptdecryptfunctionRSAECBPKCS1Padding.htm
通常如何加密较长的内容(文件):
(请注意有多种选择或模式,我在这里写的是一个简单的建议)
加密:
- 生成随机 AES 密钥(128 位即可)和随机数 (IV) - 对于 IV,不要使用代码中的固定向量
- 使用 RSA 加密生成的密钥(例如 RSA/ECB/PKCS1Padding)
- 计算内容的摘要(哈希)(sha-256)
- 向输出流写入加密的 AES 密钥、IV、摘要和加密内容 (AES/CBC/PKCS5Padding)。
解密
- 从流中读取 AES 密钥、随机数和摘要
- 使用您的 RSA 私钥解密密钥
- 阅读并解密内容
- 计算解密内容的摘要并将其与已读取的哈希进行比较,如果不匹配则失败
这看起来很复杂,但是跳过这些步骤中的任何一个都可能(而且经常会)导致加密被破坏。即使这些步骤也需要有一些属性(固定执行时间等,但对于开始你应该没问题)。
我有一个包含 public 密钥和私钥的 pfx 文件,我想使用这些密钥在我的机器上本地加密和解密文件。 那是我的代码:
public static void encryptFile(File file, PublicKey key,
String transformation) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException, IOException,
InvalidAlgorithmParameterException, NoSuchProviderException {
Cipher c = Cipher.getInstance(transformation, "SunJCE");
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyb, "AES");
c.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivspec);
FileInputStream is = new FileInputStream(file);
CipherOutputStream os = new CipherOutputStream(new FileOutputStream(
new File(file.getName() + "_enc")), c);
copy(is, os);
}
public static void decryptFile(File encryptedFile, File decryptedFile,
Key privateKey, String transformation) {
try {
Cipher c = Cipher.getInstance(transformation, "SunJCE");
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
byte[] keyb = privateKey.getEncoded();
SecretKeySpec secretKeySpec = new SecretKeySpec(keyb, "AES");
c.init(Cipher.DECRYPT_MODE, secretKeySpec, ivspec);
CipherInputStream is = new CipherInputStream(new FileInputStream(
encryptedFile), c);
FileOutputStream os = new FileOutputStream(decryptedFile);
copy(is, os);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void copy(InputStream is, OutputStream os) {
try {
byte[] buf = new byte[1024];
long total = 0;
while (true) {
int r = is.read(buf);
if (r == -1) {
break;
}
os.write(buf, 0, r);
total += r;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
is.close();
os.flush();
os.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
我这样称呼它:
CertificateHandler.encryptFile(new File("test.pdf"), pb, "AES/CBC/PKCS5Padding");
CertificateHandler.decryptFile(new File("test.pdf_enc"), new File("test.enc.pdf"), pk, "AES/CBC/NoPadding");
但是我得到这个错误:
java.security.InvalidKeyException: Invalid AES key length: 294 bytes
我使用了 Unlimited JCE Policy 但没有任何改变。当我尝试使用摘要密钥时,我认为它不起作用,因为它被切断了,不再有效
有什么建议吗?
为了正确加密,您遗漏了一些细节。
AES 是一种对称密码,采用密钥大小为 128、192 或 256 位。您不能仅将 RSA 私钥与任何加密方案一起使用。
要使用 RSA 密钥,只需在网上搜索,例如 http://www.java2s.com/Code/Android/Security/RSAencryptdecryptfunctionRSAECBPKCS1Padding.htm
通常如何加密较长的内容(文件):
(请注意有多种选择或模式,我在这里写的是一个简单的建议)
加密:
- 生成随机 AES 密钥(128 位即可)和随机数 (IV) - 对于 IV,不要使用代码中的固定向量
- 使用 RSA 加密生成的密钥(例如 RSA/ECB/PKCS1Padding)
- 计算内容的摘要(哈希)(sha-256)
- 向输出流写入加密的 AES 密钥、IV、摘要和加密内容 (AES/CBC/PKCS5Padding)。
解密
- 从流中读取 AES 密钥、随机数和摘要
- 使用您的 RSA 私钥解密密钥
- 阅读并解密内容
- 计算解密内容的摘要并将其与已读取的哈希进行比较,如果不匹配则失败
这看起来很复杂,但是跳过这些步骤中的任何一个都可能(而且经常会)导致加密被破坏。即使这些步骤也需要有一些属性(固定执行时间等,但对于开始你应该没问题)。