Ed25519是一个数字签名算法,签名和验证的性能都极高。
gradle引入jar包依赖:
compile("org.whispersystems:curve25519-android:0.5.0")
compile("net.i2p.crypto:eddsa:0.3.0")
新建TestUtil工具类
package com.ly.mp.project.utils;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SignatureException;
import java.util.Base64;
import net.i2p.crypto.eddsa.EdDSAEngine;
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
import net.i2p.crypto.eddsa.EdDSAPublicKey;
import net.i2p.crypto.eddsa.KeyPairGenerator;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
public class TestUtil {
/**
* ed25519生成密钥对
* @return
*/
public static KeyPair ed25519GerateKeyPair() {
KeyPairGenerator edDsaKpg = new KeyPairGenerator();
KeyPair keyPair = edDsaKpg.generateKeyPair();
return keyPair;
}
/**
* ed25519签名
* @param privateKey
* @param data
* @throws Exception
*/
public static String ed25519Sign(PrivateKey privateKey, byte[] data) throws Exception {
EdDSAEngine edEng = new EdDSAEngine();
//edEng.initSign(getEd25519PrivateKey(privateKey));
edEng.initSign(privateKey);
edEng.setParameter(EdDSAEngine.ONE_SHOT_MODE);
edEng.update(data);
byte[] enEdata = edEng.sign();
return Base64.getEncoder().encodeToString(enEdata);
}
public static PrivateKey getEd25519PrivateKey(String privateKey) {
EdDSANamedCurveSpec spec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519);
return new EdDSAPrivateKey(new EdDSAPrivateKeySpec(Base64.getDecoder().decode(privateKey), spec));
}
/**
* ed25519验签
* @param data
* @param signData
* @return
* @throws SignatureException
* @throws InvalidAlgorithmParameterException
* @throws InvalidKeyException
*/
public static Boolean ed25519VerifySign(String publicKey, String data, String signData) throws SignatureException, InvalidAlgorithmParameterException, InvalidKeyException {
EdDSAEngine edEng = new EdDSAEngine();
EdDSANamedCurveSpec spec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519);
byte[] publicKeyByte = Base64.getDecoder().decode(publicKey);
PublicKey pk = new EdDSAPublicKey(new EdDSAPublicKeySpec(publicKeyByte, spec));
edEng.initVerify(pk);
edEng.setParameter(EdDSAEngine.ONE_SHOT_MODE);
edEng.update(data.getBytes());
Boolean isSuccess = edEng.verify(Base64.getDecoder().decode(signData));
return isSuccess;
}
public static Boolean ed25519VerifySign(PublicKey publicKey, String data, String signData) throws SignatureException, InvalidAlgorithmParameterException, InvalidKeyException {
EdDSAEngine edEng = new EdDSAEngine();
edEng.initVerify(publicKey);
edEng.setParameter(EdDSAEngine.ONE_SHOT_MODE);
edEng.update(data.getBytes());
Boolean isSuccess = edEng.verify(Base64.getDecoder().decode(signData));
return isSuccess;
}
public static void main(String[] args) {
KeyPair keyPair = VaultPrefixUtil.ed25519GerateKeyPair();
EdDSAPrivateKey pv = (EdDSAPrivateKey) keyPair.getPrivate();
String privateKey = Base64.getEncoder().encodeToString(pv.getSeed());
String publicKey = Base64.getEncoder().encodeToString(pv.getAbyte());
System.out.println("privateKey:" + privateKey);
System.out.println("publicKey:" + publicKey);
// byte[] pb = Base64.getDecoder().decode(publicKey);
// EdDSANamedCurveSpec spec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519);
// EdDSAPublicKey pk = new EdDSAPublicKey(new EdDSAPublicKeySpec(pb, spec));
String data = "123我";
String signData = "";
try {
signData = VaultPrefixUtil.ed25519Sign(pv, data.getBytes("UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("signData:" + signData);
System.out.println("privateKeyLength=" + Base64.getDecoder().decode(privateKey).length);
try {
Boolean flag = VaultPrefixUtil.ed25519VerifySign(publicKey, data, signData);
System.out.println(flag);
} catch (InvalidKeyException | SignatureException | InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
}
}
运行main方法输出如下:
privateKey:1thlaSJ3ttRZwP7qYPFvM2p9QBTsPNiiisB7eQs8G+U=
publicKey:3YhBvpTK+NcpVl8ASJr90Yfcvx3Oj28EQ5FTcO9P9QI=
signData:Luyg26nhRtWNwuMKiWOcivnSiWhqSN7K7TER4oZ/xKOOLKwnC6optI6MOiywLyKYXYdvmeJeS17dmwR94/N+Cw==
privateKeyLength=32
true
可以看到加签验签都是成功的。