RSA加密Javascript和解密Java
用不同的组合花了将近2天的时间。我正在使用RSA算法在java中生成一个非对称密钥对(公共密钥和私有密钥),并尝试使用javascript中的公钥加密一些文本,然后在服务器端用java进行解密。我在尝试解密用javascript加密的字符串时遇到“javax.crypto.IllegalBlockSizeException:数据长度不得超过128字节”异常。非常感谢你的帮助
使用该Javascript库进行加密强>
https://github.com/wwwtyro/cryptico
var publicKeyString=”“//在java中生成的base64编码公钥字符串
这是我的javascript代码
var EncryptionResult = cryptico.encrypt("somestring", publicKeyString);
console.log("Encrypted status-"+EncryptionResult.status);
console.log("Encrypted String-"+EncryptionResult.cipher);
它正在成功加密字符串
Java密钥生成和解密
Cipher cipher = Cipher.getInstance("RSA");
KeyFactory fact = KeyFactory.getInstance("RSA");
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024); // 1024 used for normal
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
FileOutputStream fos = null;
ObjectOutputStream oos = null;
在解密方法中用于解密的文件中存储私钥的代码
RSAPrivateKeySpec rsaPrivKeySpec = fact.getKeySpec(privateKey,
RSAPrivateKeySpec.class);
System.out.println("Writing private key...");
fos = new FileOutputStream(PRIVATE_KEY_FILE);
oos = new ObjectOutputStream(new BufferedOutputStream(fos));
oos = new ObjectOutputStream(new BufferedOutputStream(fos));
oos.writeObject(rsaPrivKeySpec.getModulus());
oos.writeObject(rsaPrivKeySpec.getPrivateExponent());
oos.close();
解密方法
public String decrypt(String ciphertext)
throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException
{
if (ciphertext.length() == 0) return null;
byte[] dec = org.apache.commons.codec.binary.Base64.decodeBase64(ciphertext);
try {
System.out.println("Private Key file name----"+PRIVATE_KEY_FILE);
privateKey = readPrivateKeyFromFile(PRIVATE_KEY_FILE);
} catch (IOException e) {
e.printStackTrace();
}
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decrypted = cipher.doFinal(dec);
return new String(decrypted, PLAIN_TEXT_ENCODING);
}
//reading private key from file
public PrivateKey readPrivateKeyFromFile(String fileName)
throws IOException {
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fis = new FileInputStream(new File(fileName));
ois = new ObjectInputStream(fis);
System.out.println("Private Key file-"+fileName);
BigInteger modulus = (BigInteger) ois.readObject();
BigInteger exponent = (BigInteger) ois.readObject();
// Get Private Key
RSAPrivateKeySpec rsaPrivateKeySpec = new RSAPrivateKeySpec(modulus, exponent);
KeyFactory fact = KeyFactory.getInstance("RSA");
PrivateKey privateKey = fact.generatePrivate(rsaPrivateKeySpec);
return privateKey;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ois != null) {
ois.close();
if (fis != null) {
fis.close();
}
}
}
return null;
}
# 1 楼答案
从
Cryptico
文档来看,这似乎不是一个简单的RSA加密,而是一个复杂的操作,它生成AES密钥,用RSA加密,用AES加密数据,并输出加密AES密钥和加密数据的串联。如果你想在Java中解密,你必须检查Cryptico
源代码,并在Java中重新实现至于您当前的尝试和
javax.crypto.IllegalBlockSizeException: Data must not be longer than 128 bytes
错误:如果未指定完整转换,RSA的默认JCE转换为RSA/ECB/PKCS1Padding
在此模式下,RSA加密或解密长度不大于密钥大小的单个数据块(更具体地说,如果字节的输入序列被解释为大整数,则其值应小于RSA使用的模)。你可以在this和this问题中找到更多信息
密钥大小为1024位时,最大数据大小为128字节,这正是异常所说的,因为
Cryptico
的输出显然不是单个RSA块,其长度大于“普通”RSA预期的长度。在Java中尝试使用其他密码模式或填充模式在这种情况下也不会有帮助# 2 楼答案
感谢Oleg提供的详细信息。我一定会调查的
现在我切换到jsencrypt,它似乎工作得很好
https://github.com/travist/jsencrypt
编辑
如何获取js加密的编码公钥
# 3 楼答案
下面是JS数据加密和Java(服务器端)解密的解决方案。我使用了Cryptico js库进行加密(http://wwwtyro.github.io/cryptico/)
首先,我们必须从本地系统生成java密钥库文件。不要使用其他密钥库文件,如联机密钥库。要创建java密钥库(JKS),可以使用密钥库资源管理器工具
下面是我使用的配置,使用密钥库资源管理器工具
最后,将文件另存为。本地系统上的jks
步骤1
我们必须在java端使用这个密钥库文件,并将公钥发送到前端
我已经创建了服务类,它负责从密钥库文件路径(字符串)、密钥对和解密加载密钥库。您必须提供别名、密码、密钥库类型
decryptData()方法将在此处扮演主要角色。当您发送值数据时。getBytes()直接指向dycrypt方法
cipher.doFinal(byteArray)
您会得到异常-IllegalBlockSizeException大小不应超过128字节。所以我们已经解决了这个问题,我在这里找到了解决办法-[Getting 1 byte extra in the modulus RSA Key and sometimes for exponents also 基本上,当我们将数据从BigInteger转换为byteArray时,它会添加零。所以我从数组中删除了零让我们开始使用服务类来获取键值
将公钥发送给JS。 在HTML或servlet中导入所有必需的js和jar文件(您将从cryptico js库中获得)
上面我直接使用了
new RSA()
实例(在cryptico库中它将不同。Internaly库使用相同的)并将公钥设置为实例。我们必须使用十六进制字符串值为“10001”。使用发送到服务器的加密数据形成查询字符串。表单数据保存加密数据以及“dataEncrypt”密钥值。我过去经常检查数据是否加密最后,在服务器端,您将获得请求参数,下面是用于解密的代码