我注意到Java中有一个CipherOutputStream,但显然没有SignatureOutputStream。这是真的?我在哪里可以找到SignatureOutputStream?
答案 0 :(得分:6)
以下是一个示例实现,仅供您使用。它带有测试功能(见下文)。
package de.fencing_game.paul.examples;
import java.io.*;
import java.security.*;
/**
* This class provides an outputstream which writes everything
* to a Signature as well as to an underlying stream.
*/
public class SignatureOutputStream
extends OutputStream
{
private OutputStream target;
private Signature sig;
/**
* creates a new SignatureOutputStream which writes to
* a target OutputStream and updates the Signature object.
*/
public SignatureOutputStream(OutputStream target, Signature sig) {
this.target = target;
this.sig = sig;
}
public void write(int b)
throws IOException
{
write(new byte[]{(byte)b});
}
public void write(byte[] b)
throws IOException
{
write(b, 0, b.length);
}
public void write(byte[] b, int offset, int len)
throws IOException
{
target.write(b, offset, len);
try {
sig.update(b, offset, len);
}
catch(SignatureException ex) {
throw new IOException(ex);
}
}
public void flush()
throws IOException
{
target.flush();
}
public void close()
throws IOException
{
target.close();
}
}
以下是一些测试方法,用于说明如何使用它:
private static byte[] signData(OutputStream target,
PrivateKey key, String[] data)
throws IOException, GeneralSecurityException
{
Signature sig = Signature.getInstance("SHA1withRSA");
sig.initSign(key);
DataOutputStream dOut =
new DataOutputStream(new SignatureOutputStream(target, sig));
for(String s : data) {
dOut.writeUTF(s);
}
byte[] signature = sig.sign();
return signature;
}
private static void verify(PublicKey key, byte[] signature,
byte[] data)
throws IOException, GeneralSecurityException
{
Signature sig = Signature.getInstance("SHA1withRSA");
sig.initVerify(key);
ByteArrayOutputStream collector =
new ByteArrayOutputStream(data.length);
OutputStream checker = new SignatureOutputStream(collector, sig);
checker.write(data);
if(sig.verify(signature)) {
System.err.println("Signature okay");
}
else {
System.err.println("Signature falsed!");
}
}
/**
* a test method.
*/
public static void main(String[] params)
throws IOException, GeneralSecurityException
{
if(params.length < 1) {
params = new String[] {"Hello", "World!"};
}
KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
KeyPair pair = gen.generateKeyPair();
ByteArrayOutputStream arrayStream = new ByteArrayOutputStream();
byte[] signature = signData(arrayStream, pair.getPrivate(), params);
byte[] data = arrayStream.toByteArray();
verify(pair.getPublic(), signature, data);
// change one byte by one
data[3]++;
verify(pair.getPublic(), signature, data);
data = arrayStream.toByteArray();
verify(pair.getPublic(), signature, data);
// change signature
signature[4]++;
verify(pair.getPublic(), signature, data);
}
main方法使用新的(随机)私钥对其命令行参数进行签名,然后使用相应的公钥对其进行检查。它再次用一点改变的数据和签名来检查它。
当然,为了检查签名,SignatureInputStream
会更有用 - 你可以用同样的方式创建它。