Java 安全性 - RSA 公钥和私钥代码问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18757114/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java Security - RSA Public Key & Private Key Code Issue
提问by Priyan RockZ
Here is my error
这是我的错误
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: DerInputStream.getLength(): lengthTag=127, too big.
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(Unknown Source)
at java.security.KeyFactory.generatePublic(Unknown Source)
at com.sanjaya.rsa.PublicKeyReader.get(PublicKeyReader.java:22)
at com.sanjaya.rsa.MainKeyClass.main(MainKeyClass.java:8)
Caused by: java.security.InvalidKeyException: IOException: DerInputStream.getLength(): lengthTag=127, too big.
at sun.security.x509.X509Key.decode(Unknown Source)
at sun.security.x509.X509Key.decode(Unknown Source)
at sun.security.rsa.RSAPublicKeyImpl.<init>(Unknown Source)
at sun.security.rsa.RSAKeyFactory.generatePublic(Unknown Source)
... 4 more
Here is my code - MAIN CLASS
这是我的代码 -主类
public static void main(String[] args) {
PublicKeyReader publicKeyReader=new PublicKeyReader();
try {
publicKeyReader.get("c:\public.key");
} catch (Exception e) {
e.printStackTrace();
}
PrivateKeyReader privateKeyReader=new PrivateKeyReader();
try {
privateKeyReader.get("c:\private.key");
} catch (Exception e) {
e.printStackTrace();
}
Here is public key related method
这是公钥相关的方法
public static PublicKey get(String filename) throws Exception {
File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int)f.length()];
dis.readFully(keyBytes);
dis.close();
X509EncodedKeySpec spec =new X509EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
Here is private key related method
这里是私钥相关的方法
public static PrivateKey get(String filename)throws Exception {
File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int)f.length()];
dis.readFully(keyBytes);
dis.close();
PKCS8EncodedKeySpec spec =new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}
Please help me to sort out this issue
请帮我解决这个问题
Need to create public key & private key & Encrypt ,decrypt string from those under RSA encyption
需要创建公钥 & 私钥 & 加密, 解密来自 RSA 加密下的字符串
采纳答案by Shankar Murthy
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.KeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
class RSA{
public static void main(String[] args) throws Exception {
generateKeys();
rsaEncrypt("plaintext.txt", "encrypted.txt");
rsaDecrypt("encrypted.txt", "decrypted.txt");
}
public static void generateKeys() throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp = kpg.genKeyPair();
PublicKey publicKey = kp.getPublic();
PrivateKey privateKey = kp.getPrivate();
System.out.println("keys created");
KeyFactory fact = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pub = fact.getKeySpec(publicKey,
RSAPublicKeySpec.class);
RSAPrivateKeySpec priv = fact.getKeySpec(privateKey,
RSAPrivateKeySpec.class);
saveToFile("public.key", pub.getModulus(), pub.getPublicExponent());
saveToFile("private.key", priv.getModulus(), priv.getPrivateExponent());
System.out.println("keys saved");
}
public static void saveToFile(String fileName, BigInteger mod,
BigInteger exp) throws IOException {
ObjectOutputStream fileOut = new ObjectOutputStream(
new BufferedOutputStream(new FileOutputStream(fileName)));
try {
fileOut.writeObject(mod);
fileOut.writeObject(exp);
} catch (Exception e) {
throw new IOException("Unexpected error");
} finally {
fileOut.close();
System.out.println("Closed writing file.");
}
}
// Return the saved key
static Key readKeyFromFile(String keyFileName) throws IOException {
InputStream in = new FileInputStream(keyFileName);
ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(
in));
try {
BigInteger m = (BigInteger) oin.readObject();
BigInteger e = (BigInteger) oin.readObject();
KeyFactory fact = KeyFactory.getInstance("RSA");
if (keyFileName.startsWith("public"))
return fact.generatePublic(new RSAPublicKeySpec(m, e));
else
return fact.generatePrivate(new RSAPrivateKeySpec(m, e));
} catch (Exception e) {
throw new RuntimeException("Spurious serialisation error", e);
} finally {
oin.close();
System.out.println("Closed reading file.");
}
}
// Use this PublicKey object to initialize a Cipher and encrypt some data
public static void rsaEncrypt(String file_loc, String file_des)
throws Exception {
FileReader file = new FileReader("C://myprograms//plaintext.txt");
BufferedReader reader = new BufferedReader(file);
String text = "";
String line = reader.readLine();
while(line!= null)
{
text += line;
line = reader.readLine();
}
reader.close();
System.out.println(text);
byte[] data = new byte[32];
int i;
System.out.println("start encyption");
Key pubKey = readKeyFromFile("public.key");
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
FileInputStream fileIn = new FileInputStream(file_loc);
FileOutputStream fileOut = new FileOutputStream(file_des);
CipherOutputStream cipherOut = new CipherOutputStream(fileOut, cipher);
// Read in the data from the file and encrypt it
while ((i = fileIn.read(data)) != -1) {
cipherOut.write(data, 0, i);
}
// Close the encrypted file
cipherOut.close();
fileIn.close();
System.out.println("encrypted file created");
}
// Use this PublicKey object to initialize a Cipher and decrypt some data
public static void rsaDecrypt(String file_loc, String file_des)
throws Exception {
byte[] data = new byte[32];
int i;
System.out.println("start decyption");
Key priKey = readKeyFromFile("private.key");
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, priKey);
FileInputStream fileIn = new FileInputStream(file_loc);
CipherInputStream cipherIn = new CipherInputStream(fileIn, cipher);
FileOutputStream fileOut = new FileOutputStream(file_des);
// Write data to new file
while ((i = cipherIn.read()) != -1) {
fileOut.write(i);
}
// Close the file
fileIn.close();
cipherIn.close();
fileOut.close();
System.out.println("decrypted file created");
}
}
This program encrypts the text in plaintext.txt file and saves the cipher text in encrypted.txt file. Similarly decryption is done using encrypted.txt file and plain text is saved in decrypted.txt file .#
该程序对plaintext.txt 文件中的文本进行加密,并将密文保存在encrypted.txt 文件中。类似的解密是使用encrypted.txt文件完成的,纯文本保存在decrypted.txt文件中。#
回答by Greg
Check the cert file's newline characters! I had a cert with Unix-style newline chars. I was attempting to use gradle to bundle my cert into a WAR, and I was also having gradle do some string replacements on the files in my WAR. However, gradle was converting everything it processed to Windows-style newline chars. This caused the InvalidKeyException. Excluding my cert files from gradle's processing fixed the problem:
检查证书文件的换行符!我有一个带有 Unix 样式换行符的证书。我试图使用 gradle 将我的证书捆绑到一个 WAR 中,并且我还让 gradle 对我的 WAR 中的文件进行一些字符串替换。但是,gradle 正在将它处理的所有内容转换为 Windows 样式的换行符。这导致了 InvalidKeyException。从 gradle 的处理中排除我的证书文件解决了这个问题:
webInf {
from myProjectFiles eachFile { projectFile
if (!projectFile.path.contains( myCertFiles ) {
filter { line ->
line.replace(someKey, someValue)
}
}
}
archiveName = 'myProject.war'