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,但它没有奏效!!