Java Ed25519 算法的签名与验签

1,283 阅读2分钟

Ed25519EdDSA (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();

使用 Base64byte[] 转为 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);