Ed25519 是 EdDSA (Edwards-Curve Digital Signature Algorithm) [RFC 8032] 中的一个数字签名算法,在 Java 15 中被添加 [JEP 339]。
所以需要注意的是,若想使用 EdDSA 及其系列中的 Ed25519 和 Ed448 数字签名算法,则需要 Java 15 及以上版本。
本文将直接使用 java.security 包来实现 Ed25519 算法的数字签名和验签。
1. 生成公钥密钥对
使用 KeyPairGenerator 生成公钥密钥对。
KeyPairGenerator ed25519 = KeyPairGenerator.getInstance("Ed25519");
KeyPair keyPair = ed25519.generateKeyPair();
PublicKey aPublic = keyPair.getPublic();
PrivateKey aPrivate = keyPair.getPrivate();
2. Sign 签名
通过 getInstance() 获取 Signature 对象,参数需填写为 Ed25519。
Signature signEncode = Signature.getInstance("Ed25519");
初始化 signEncode 签名对象,需传入上述中生成的 Ed25519 私钥 aPrivate。
signEncode.initSign(aPrivate);
设置要签名的数据,参数类型需为 byte[]。
signEncode.update(msg.getBytes());
sign() 进行签名,得到签名后的数据,类型为 byte[] 字节数组。
byte[] signBytes = signEncode.sign();
使用 Base64 将 byte[] 转为 String 字符串,便于打印查看签名后的数据。
String encodedMsg = Base64.getEncoder().encodeToString(signBytes);
System.out.println(encodedMsg);
3. Verify 验签
通过 getInstance() 获取 Signature 对象,参数需填写为 Ed25519。
Signature signDecode = Signature.getInstance("Ed25519");
初始化 signDecode 验签对象,需传入上述中生成的 Ed25519 公钥 aPublic。
signDecode.initVerify(aPublic);
设置要验签的数据,参数类型需为 byte[]。
signDecode.update(msg.getBytes());
verify() 进行验签,返回参数为 boolean 类型,当返回值为 true 时则验签成功,反之亦然。
boolean verify = signDecode.verify(Base64.getDecoder().decode(encodedMsg));
System.out.println(verify);
假设传入需要签名的 msg 信息为 "test msg",最后运行打印的结果为:
0G6wJecybsFPGznXxfMMJEyAxSfVYyVSelv33MXdcK7PYISArbLdqY61BT3p0/IqfviLGOmoorzLqb5txx2FBA==
true
本文的全部示例代码:
String msg = "test msg";
KeyPairGenerator ed25519 = KeyPairGenerator.getInstance("Ed25519");
KeyPair keyPair = ed25519.generateKeyPair();
PublicKey aPublic = keyPair.getPublic();
PrivateKey aPrivate = keyPair.getPrivate();
Signature signEncode = Signature.getInstance("Ed25519");
signEncode.initSign(aPrivate);
signEncode.update(msg.getBytes());
byte[] signedBytes = signEncode.sign();
String encodedMsg = Base64.getEncoder().encodeToString(signedBytes);
System.out.println(encodedMsg);
Signature signDecode = Signature.getInstance("Ed25519");
signDecode.initVerify(aPublic);
signDecode.update(msg.getBytes());
boolean verify = signDecode.verify(signedBytes);
System.out.println(verify);