你能帮我找一个简单的教程,讲解如何在java中使用ECDSA算法对字符串进行签名。但是没有使用任何像bouncycastle这样的第三方库。只是JDK 7.我发现很难搜索一个简单的例子,我是密码学的新手。
import java.io.*;
import java.security.*;
public class GenSig {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
/*
* Generate a DSA signature
*/
try {
/*
* Generate a key pair
*/
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", "SUN");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
keyGen.initialize(1024, random);
KeyPair pair = keyGen.generateKeyPair();
PrivateKey priv = pair.getPrivate();
PublicKey pub = pair.getPublic();
/*
* Create a Signature object and initialize it with the private key
*/
Signature dsa = Signature.getInstance("SHA1withDSA", "SUN");
dsa.initSign(priv);
String str = "This is string to sign";
byte[] strByte = str.getBytes();
dsa.update(strByte);
/*
* Now that all the data to be signed has been read in, generate a
* signature for it
*/
byte[] realSig = dsa.sign();
System.out.println("Signature: " + new String(realSig));
} catch (Exception e) {
System.err.println("Caught exception " + e.toString());
}
}
}
如何为ECDSA修改它?
答案 0 :(得分:19)
以下是基于您的示例的小示例。
注意:这是此答案的原始代码,请参阅下一个代码段以获取更新版本。
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
public class ECDSAExample {
public static void main(String[] args) throws Exception {
/*
* Generate an ECDSA signature
*/
/*
* Generate a key pair
*/
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
keyGen.initialize(256, random);
KeyPair pair = keyGen.generateKeyPair();
PrivateKey priv = pair.getPrivate();
PublicKey pub = pair.getPublic();
/*
* Create a Signature object and initialize it with the private key
*/
Signature dsa = Signature.getInstance("SHA1withECDSA");
dsa.initSign(priv);
String str = "This is string to sign";
byte[] strByte = str.getBytes("UTF-8");
dsa.update(strByte);
/*
* Now that all the data to be signed has been read in, generate a
* signature for it
*/
byte[] realSig = dsa.sign();
System.out.println("Signature: " + new BigInteger(1, realSig).toString(16));
}
}
更新:以下是删除弃用算法的略微改进示例。它还使用RFC 8422.中指定的SECG符号“secp256r1”明确请求NIST P-256曲线
import javax.xml.bind.DatatypeConverter;
import java.security.*;
import java.security.spec.ECGenParameterSpec;
public class ECDSAExample {
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws Exception {
/*
* Generate an ECDSA signature
*/
/*
* Generate a key pair
*/
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
keyGen.initialize(new ECGenParameterSpec("secp256r1"), new SecureRandom());
KeyPair pair = keyGen.generateKeyPair();
PrivateKey priv = pair.getPrivate();
PublicKey pub = pair.getPublic();
/*
* Create a Signature object and initialize it with the private key
*/
Signature ecdsa = Signature.getInstance("SHA256withECDSA");
ecdsa.initSign(priv);
String str = "This is string to sign";
byte[] strByte = str.getBytes("UTF-8");
ecdsa.update(strByte);
/*
* Now that all the data to be signed has been read in, generate a
* signature for it
*/
byte[] realSig = ecdsa.sign();
System.out.println("Signature: " + DatatypeConverter.printHexBinary(realSig));
}
}
答案 1 :(得分:1)
class ECCCipher {
@Override
public byte[] sign(PrivateKey privateKey, String message) throws Exception {
Signature signature = Signature.getInstance("SHA1withECDSA");
signature.initSign(privateKey);
signature.update(message.getBytes());
return signature.sign();
}
@Override
public boolean verify(PublicKey publicKey, byte[] signed, String message) throws Exception {
Signature signature = Signature.getInstance("SHA1withECDSA");
signature.initVerify(publicKey);
signature.update(message.getBytes());
return signature.verify(signed);
}
}
========================
public class ECCCipherTest {
private final KeyPairGenerator keygen;
public ECCCipherTest() throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
Security.addProvider(new BouncyCastleProvider());
this.keygen = KeyPairGenerator.getInstance("ECDSA", "BC");
keygen.initialize(new ECGenParameterSpec("brainpoolP384r1"));
}
@Test
public void ECC_CipherTest_1() throws Exception {
String message = "hello world";
ICipher<PrivateKey, PublicKey> cipher = new ECCCipher();
KeyPair keyPair = keygen.generateKeyPair();
byte[] encrypted = cipher.sign(keyPair.getPrivate(), message);
Assert.assertTrue(cipher.verify(keyPair.getPublic(), encrypted, message));
}
}
这是我项目中的一个小代码片段。 这个对我有用。我也包括了一个junit测试; 希望这会有所帮助。
万一有人想知道我们如何加载私钥和pubkey: (注意:privKey是表示java中BigInteger的字节数组,而pubKey是二进制格式的曲线点)
@Override
public PrivateKey generatePrivateKey(byte[] keyBin) throws InvalidKeySpecException, NoSuchAlgorithmException {
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
KeyFactory kf = KeyFactory.getInstance("ECDSA", new BouncyCastleProvider());
ECNamedCurveSpec params = new ECNamedCurveSpec("secp256k1", spec.getCurve(), spec.getG(), spec.getN());
ECPrivateKeySpec privKeySpec = new ECPrivateKeySpec(new BigInteger(keyBin), params);
return kf.generatePrivate(privKeySpec);
}
@Override
public PublicKey generatePublicKey(byte[] keyBin) throws InvalidKeySpecException, NoSuchAlgorithmException {
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
KeyFactory kf = KeyFactory.getInstance("ECDSA", new BouncyCastleProvider());
ECNamedCurveSpec params = new ECNamedCurveSpec("secp256k1", spec.getCurve(), spec.getG(), spec.getN());
ECPoint point = ECPointUtil.decodePoint(params.getCurve(), keyBin);
ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(point, params);
return kf.generatePublic(pubKeySpec);
}