java.security.NoSuchAlgorithmException:RSA签名不可用
这是例外
线程“main”中的exceptionjava.security.NoSuchAlgorithmException:RSA签名不可用 在java.security.Signature.getInstance(Signature.java:229) 在MailClient.main(MailClient.java:52)
这是我的代码
import java.io.*; import java.net.*; import java.nio.ByteBuffer; import java.util.*; import java.security.*; public class MailClient { public String getMessage(Mail m){ return m.message; } public static void main(String[] args) throws Exception { // Initialisation BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String host = args[0]; int port = Integer.parseInt(args[1]); String userid = args[2]; while(true) { // connect to server Socket s = new Socket(host,port); DataInputStream dis = new DataInputStream(s.getInputStream()); DataOutputStream dos = new DataOutputStream(s.getOutputStream()); ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream()); oos.flush(); ObjectInputStream ois = new ObjectInputStream(s.getInputStream()); // TO DO: login // these two lines are here just to make the supplied programs run without crashing. // You may want to change them, and certainly add things after them dos.writeUTF(userid); String userPrivateKeyFileName = userid + ".prv"; // Get the key to create the signature ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream(userPrivateKeyFileName)); PrivateKey privateKey = (PrivateKey)keyIn.readObject(); keyIn.close(); // create timeStamp and random number long t1 = (new Date()).getTime(); double q1 = Math.random(); // ByteBuffer to convert to bytes later ByteBuffer bb = ByteBuffer.allocate(16); bb.putLong(t1); bb.putDouble(q1); // create signature, using timeStamp and random number as data Signature sig = Signature.getInstance("RSA"); sig.initSign(privateKey); sig.update(bb.array()); byte[] signature = sig.sign(); // send data and signature DataOutputStream out = new DataOutputStream(s.getOutputStream()); out.writeUTF(userid); out.writeLong(t1); out.writeDouble(q1); out.writeInt(signature.length); out.write(signature); out.flush(); boolean answer = dis.readBoolean(); //passed the verifyLogin if (answer) { // receive how many messages int numMsg = dis.readInt(); System.out.println("You have " + numMsg + " incoming messages."); // TO DO: read messages ArrayList msg = new ArrayList(numMsg); for(int i=0;i<numMsg;i++){ //@Unchecked msg = (ArrayList) ois.readObject(); } while(!msg.isEmpty()){ //for each mail, display sender,timestamp,message System.out.println(msg.get(0).sender); System.out.println(msg.get(0).timestamp); System.out.println(msg.get(0).message); MessageDigest md = MessageDigest.getInstance("SHA-1"); md.update(msg.get(0).hashcash); byte[] digest = md.digest(); boolean normalMail = msg.get(0).checkHashcash(digest); if(normalMail){ //check each mail is original that it isn't modified //receive mail System.out.println(msg.get(0).message); } else{System.out.println("it's a spam message."); System.out.println(msg.get(0).message); } msg.remove(0); } // send messages System.out.println("Do you want to send a message [Y/N]?"); String wantToSend = br.readLine(); if (!wantToSend.equals("Y")) { dos.writeBoolean(false); return ; } dos.writeBoolean(true); System.out.println("Enter userid of recipient:"); String recipient = br.readLine(); System.out.println("Type your message:"); String message = br.readLine(); // TO DO: send mail Mail m = new Mail(userid, recipient, message); MessageDigest md = MessageDigest.getInstance("SHA-1"); md.update(m.hashcash); byte[] digest = md.digest(); while(m.checkHashcash(digest)){ m.setHashcash(digest); } out.write(digest); out.flush(); // send timeStamp and digest to server long mailTimestamp = m.timestamp.getTime(); out.writeLong(mailTimestamp); oos.writeObject(m); } } } }
如果运行以下代码,您将获得Java安装支持的签名算法列表。
TreeSet algorithms = new TreeSet<>(); for (Provider provider : Security.getProviders()) for (Service service : provider.getServices()) if (service.getType().equals("Signature")) algorithms.add(service.getAlgorithm()); for (String algorithm : algorithms) System.out.println(algorithm);
当我运行它(Windows,Java 1.8.0_65)时,我得到:
MD2withRSA MD5andSHA1withRSA MD5withRSA NONEwithDSA NONEwithECDSA NONEwithRSA SHA1withDSA SHA1withECDSA SHA1withRSA SHA224withDSA SHA224withECDSA SHA224withRSA SHA256withDSA SHA256withECDSA SHA256withRSA SHA384withECDSA SHA384withRSA SHA512withECDSA SHA512withRSA
如您所见, RSA
不是有效的签名算法。
也许NONEwithRSA
就是你追求的?
指定有效的算法。 需要指定哈希算法。 例如, SHA256withRSA
。
请始终参考文档
文档
我在我的机器上检查了java版本(1.7)和(1.8)支持的算法。 我的一个项目运行在jdk 1.7.0_80上,它不支持SHA224withRSA算法,如果你处于同样的情况,那么升级到java的新版本至少(Java SE 7 Update 131),因为我读过它应该有与java 8类似的算法。如果没有更新java的选项,那么尝试在pom或jar文件中添加org.bouncycastle bcprov-jdk15on maven依赖项到你的项目中以及在java代码中添加你在哪里构建SSLContext / HttpClient包含在下面的行:
Security.addProvider(new BouncyCastleProvider());
还尝试安装Java Cryptography Extension(JCE)Unlimited Strength Jurisdiction Policy Files 7,但它没有奏效!!