这是例外
Exception in thread "main" java.security.NoSuchAlgorithmException: RSA Signature not available at java.security.Signature.getInstance(Signature.java:229) at 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<Mail> msg = new ArrayList<>(numMsg);
for(int i=0;i<numMsg;i++){
//@Unchecked
msg = (ArrayList<Mail>) 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);
}
}
}
}
答案 0 :(得分:10)
如果运行以下代码,您将获得Java安装支持的签名算法列表。
TreeSet<String> 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
就是你所追求的?
答案 1 :(得分:4)
答案 2 :(得分:1)
指定有效的算法。需要指定哈希算法。例如,SHA256withRSA
。
答案 3 :(得分:0)
我已经检查了java版本(1.7)和&amp ;; (1.8)在我的机器上。我的一个项目运行在jdk 1.7.0_80上,它不支持SHA224withRSA算法,如果您处于相同的情况,那么升级到最新版本的java至少(Java SE 7 Update 131),因为我&#39 ;阅读它应该有与java 8类似的算法。如果没有更新java的选项,那么尝试在pom或jar文件中添加 org.bouncycastle bcprov-jdk15on maven依赖项你的项目&amp;也可以在java代码中添加你在哪里构建SSLContext / HttpClient包含在下面的行:
Security.addProvider(new BouncyCastleProvider());
还尝试安装Java Cryptography Extension(JCE)Unlimited Strength Jurisdiction Policy Files 7,但它还没有工作!!