JEP 497:基于模块格的抗量子数字签名算法
概括
通过提供抗量子的基于模块格的数字签名算法 (ML-DSA) 的实现来增强 Java 应用程序的安全性。数字签名用于检测对数据的未经授权的修改并验证签名者的身份。ML-DSA 旨在抵御未来的量子计算攻击。它已由美国国家标准与技术研究院 (NIST) 在FIPS 204中进行了标准化。
目标
KeyPairGenerator
提供、Signature
和API的 ML-DSA 实现KeyFactory
,并支持 FIPS 204 中标准化的参数集 ML-DSA-44、ML-DSA-65 和 ML-DSA-87。
非目标
-
实现ML-DSA 衍生自的Dilithium 算法并不是我们的目标。这两种算法不能互操作。
-
我们的目标不是为尚未制定必要标准的 Java 平台组件添加对 ML-DSA 的支持。特别是 JAR 文件签名以及软件包中的传输层安全性 (TLS) 实现
javax.net.ssl
。一旦标准制定出来,我们就会添加此类支持。 -
支持 Pre-Hash ML-DSA (FIPS 204 §5.4) 或允许用户设置特定于应用程序的上下文字符串 (FIPS 204 §5.2) 不是我们的目标。我们可能会在未来版本中实现这些功能。
动机
多年来,量子计算领域一直在稳步发展。未来的大型量子计算机可以使用Shor 算法(该算法能够分解整数和解决离散对数问题)来破坏广泛部署的基于公钥的算法(包括 Rivest-Shamir-Adleman (RSA) 和 Diffie-Hellman)的安全性。Java 平台使用此类算法对 JAR 文件进行数字签名并通过传输层安全性 (TLS) 协议建立安全网络连接等。传统超级计算机可能需要数千到数百万年才能完成的攻击,使用 Shor 算法的量子计算机只需几个小时即可完成。密码学家为应对这一威胁,发明了抗量子加密算法,Shor 算法无法破解该算法。
为了以抗量子的方式对数据进行签名和身份验证,NIST 在FIPS 204中标准化了基于模块格的数字签名算法 (ML-DSA) 。在美国,处理敏感信息的政府计算机系统必须在未来十年内升级以使用 ML-DSA。因此,Java 平台必须提供此算法的实现。
描述
我们将提供 ML-DSA 实现的KeyPairGenerator
API 来生成 ML-DSA 密钥对、Signature
API 来签署和验证 ML-DSA 签名、以及KeyFactory
API 来在 ML-DSA 密钥和其编码之间进行转换。
在Java 安全标准算法名称规范中,我们将为、和 API 定义一个新的标准"ML-DSA"
算法系列KeyPairGenerator
名称。Signature``KeyFactory
FIPS 204 为 ML-DSA 指定了三个参数集。按照安全强度增加和性能降低的顺序,它们被命名为"ML-DSA-44"
、"ML-DSA-65"
和"ML-DSA-87"
。这些参数集名称还将被定义为KeyPairGenerator
、Signature
和API 的标准算法名称,并且将由新常量、和KeyFactory
来表示。NamedParameterSpec
ML_DSA_44``ML_DSA_65``ML_DSA_87
生成 ML-DSA 密钥对
您可以通过以下三种方式之一生成 ML-DSA 密钥对:
-
使用家族名称实例化
KeyPairGenerator
并使用参数集名称初始化它:KeyPairGenerator g = KeyPairGenerator.getInstance("ML-DSA");
g.initialize(NamedParameterSpec.ML_DSA_44);
KeyPair kp = g.generateKeyPair(); // an ML-DSA-44 key pair -
如果不使用
KeyPairGenerator
参数集初始化,则实现将使用 ML-DSA-65 作为默认值:KeyPairGenerator g = KeyPairGenerator.getInstance("ML-DSA");
KeyPair kp = g.generateKeyPair(); // an ML-DSA-65 key pair -
直接
KeyPairGenerator
使用参数集名称实例化:KeyPairGenerator g = KeyPairGenerator.getInstance("ML-DSA-87");
KeyPair kp = g.generateKeyPair(); // an ML-DSA-87 key pair
APIKeyPairGenerator
允许在初始化期间指定整数密钥大小,但这不支持 ML-DSA 密钥对,并且会导致InvalidParameterException
抛出。
该keytool
命令将支持生成 ML-DSA 密钥对和证书。例如:
$ keytool -keystore ks -storepass changeit -genkeypair -alias mldsa \
-keyalg ML-DSA -groupname ML-DSA-65 -dname CN=ML-DSA
ML-DSA-65
您还可以通过以下选项直接提供参数集名称-keyalg
:
$ keytool -keystore ks -storepass changeit -genkeypair -alias mldsa \
-keyalg ML-DSA-65 -dname CN=ML-DSA2
使用 ML-DSA 密钥签名
您可以使用 ML-DSASignature
实现来签署和验证 ML-DSA 签名。
例如,使用私钥签署消息:
byte[] msg = ...;
Signature ss = Signature.getInstance("ML-DSA");
ss.initSign(privateKey);
ss.update(msg);
byte[] sig = ss.sign();
要使用公钥验证签名:
byte[] msg = ...;
byte[] sig = ...;
Signature sv = Signature.getInstance("ML-DSA");
sv.initVerify(publicKey);
sv.update(msg);
boolean verified = sv.verify(sig);
如果Signature
对象使用系列名称进行实例化,则它会接受系列中具有任何参数集的 ML-DSA 密钥。如果对象使用参数集名称进行实例化,则它仅接受使用该参数集的 ML-DSA 密钥;否则,initSign
和initVerify
方法会抛出InvalidKeyException
。
编码和解码 ML-DSA 密钥
您可以使用 ML-DSAKeyFactory
实现将 ML-DSA 私钥与其 PKCS #8 编码相互转换,或者将 ML-DSA 公钥与其 X.509 编码相互转换。
例如,将 ML-DSA 私钥转换为其 PKCS #8 编码,反之亦然:
KeyFactory f = KeyFactory.getInstance("ML-DSA");
PKCS8EncodedKeySpec p8spec = f.getKeySpec(kp.getPrivate(),
PKCS8EncodedKeySpec.class);
PrivateKey sk2 = f.generatePrivate(p8spec);
类似地,将 ML-DSA 公钥转换为其 X.509 编码,反之亦然:
X509EncodedKeySpec x509spec = f.getKeySpec(kp.getPublic(),
X509EncodedKeySpec.class);
PublicKey pk2 = f.generatePublic(x509spec);
只要支持其编码格式,实现还可以使用该方法转换KeyFactory
来自另一个安全提供程序的密钥。translateKey
ML-DSA或实现生成的对象getAlgorithm
的方法始终返回系列名称,无论或是否使用系列名称或参数集名称之一进行实例化。ML -DSA 密钥的方法返回与密钥的参数集名称匹配的对象。Key``KeyPairGenerator``KeyFactory``"ML-DSA"``KeyPairGenerator``KeyFactory``"ML-DSA"``getParams``NamedParameterSpec
如果KeyFactory
对象使用系列名称进行实例化,则它会使用任意参数集对系列中的 ML-DSA 密钥进行编码或解码。如果对象使用参数集名称进行实例化,则它仅对使用该参数集的 ML-DSA 密钥进行编码或解码;否则,该translateKey
方法会抛出InvalidKeyException
,而generatePrivate
、generatePublic
和getKeySpec
方法会抛出InvalidKeySpecException
。
ML-DSA 使用的编码在IETF RFC 草案KeyFactory
中定义。我们将跟踪此草案中的变更,直至其发布。
替代方案
-
Open Quantum Safe 项目为其C库提供了一个JNI 包装器,该库实现了包括 Dilithium 和 ML-DSA 在内的一系列抗量子算法。如果 Open Quantum Safe 实现了成为 OpenSSL、BoringSSL、OpenSSH 和 Mozilla 等主要项目的主要抗量子加密实现的目标,那么它将通过广泛的测试和使用获得显著的性能和稳健性。
liboqs
与本机实现相比,ML-DSA 的 Java 实现的主要优势在于可以直接集成到 JDK 中。这使得它可以立即在已移植 JDK 的所有平台上使用。
测试
-
KeyGenerator
单元测试将确认实现符合、Signature
和API的规范KeyFactory
,包括无效输入参数、边界值和不支持的操作等边缘情况。 -
已知答案测试 (KAT) 将涵盖有效的加密操作(正面案例)和无效操作或已知漏洞(负面案例),确保全面验证。这些将包括但不限于:
-
NIST 的密码算法验证程序服务生成的KAT(此处、此处和此处) ,以及
-
Project Wycheproof的 ML-DSA 测试目前正在开发中。
-
-
与其他供应商(包括但不限于
liboqs
)的实现进行互操作测试将确认我们的 ML-DSA 实现与其他实现配合良好。