跳到主要内容

JEP 497: 抗量子模块-基于格的数字签名算法

QWen Max 中英对照 JEP 497: Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm

概要

通过提供一种抗量子的基于模块格的数字签名算法(ML-DSA)的实现来增强 Java 应用程序的安全性。数字签名用于检测对数据未经授权的修改,并验证签署者的身份。ML-DSA 被设计为能够抵御未来的量子计算攻击。它已被美国国家标准与技术研究院(NIST)在FIPS 204中标准化。

目标

非目标

  • 实现 ML-DSA 源自的Dilithium 算法不是目标。这两种算法不能互操作。

  • 在 Java 平台的组件中为 ML-DSA 添加支持不是目标,因为这些组件所需的必要标准尚不存在。特别是 JAR 文件签名以及 javax.net.ssl 包中的传输层安全(TLS)实现就是这种情况。一旦这些标准存在,我们将添加此类支持。

  • 支持 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 平台来说,提供该算法的实现是至关重要的。

描述

我们将提供 KeyPairGenerator API 的 ML-DSA 实现来生成 ML-DSA 密钥对,提供 Signature API 的实现来签名和验证 ML-DSA 签名,以及提供 KeyFactory API 的实现来将 ML-DSA 密钥与其编码进行转换。

Java 安全标准算法名称规范 中,我们将为 KeyPairGeneratorSignatureKeyFactory API 定义一个新的标准算法族名称 "ML-DSA"

FIPS 204 规定了 ML-DSA 的三个参数集。按照安全性逐渐增强和性能逐渐降低的顺序,它们分别命名为 "ML-DSA-44""ML-DSA-65""ML-DSA-87"。这些参数集名称也将被定义为 KeyPairGeneratorSignatureKeyFactory API 的标准算法名称,并且,还将由新的 NamedParameterSpec 常量 ML_DSA_44ML_DSA_65ML_DSA_87 表示。

生成 ML-DSA 密钥对

您可以使用以下三种方法之一生成 ML-DSA 密钥对:

  • 使用家族名称实例化一个 KeyPairGenerator,并使用参数集名称进行初始化:

    KeyPairGenerator g = KeyPairGenerator.getInstance("ML-DSA");
    g.initialize(NamedParameterSpec.ML_DSA_44);
    KeyPair kp = g.generateKeyPair(); // 一个 ML-DSA-44 密钥对
  • 如果你没有用参数集初始化 KeyPairGenerator,实现将默认使用 ML-DSA-65:

    KeyPairGenerator g = KeyPairGenerator.getInstance("ML-DSA");
    KeyPair kp = g.generateKeyPair(); // 一个 ML-DSA-65 密钥对
  • 直接使用参数集名称实例化一个 KeyPairGenerator

    KeyPairGenerator g = KeyPairGenerator.getInstance("ML-DSA-87");
    KeyPair kp = g.generateKeyPair(); // 一个 ML-DSA-87 密钥对

KeyPairGenerator API 允许在初始化期间指定一个整数密钥大小,但这不支持 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

您还可以通过 -keyalg 选项直接提供参数集名称 ML-DSA-65

$ keytool -keystore ks -storepass changeit -genkeypair -alias mldsa \
-keyalg ML-DSA-65 -dname CN=ML-DSA2

使用 ML-DSA 密钥签名

你可以使用 ML-DSA Signature 实现来签名和验证 ML-DSA 签名。

例如,使用私钥签名消息:

sign_message(private_key, message)
python
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 密钥;否则,initSigninitVerify 方法将抛出一个 InvalidKeyException

编码和解码 ML-DSA 密钥

你可以使用 ML-DSA KeyFactory 实现将 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 KeyPairGeneratorKeyFactory 实现生成的 Key 对象的 getAlgorithm 方法总是返回族名称 "ML-DSA",无论 KeyPairGeneratorKeyFactory 是用 "ML-DSA" 族名称还是其中一个参数集名称实例化的。ML-DSA 密钥的 getParams 方法返回一个与密钥的参数集名称匹配的 NamedParameterSpec 对象。

如果使用族名称实例化 KeyFactory 对象,它将对族中任何参数集的 ML-DSA 密钥进行编码或解码。如果使用参数集名称实例化,则它仅对使用该参数集的 ML-DSA 密钥进行编码或解码;否则,translateKey 方法将抛出 InvalidKeyException,而 generatePrivategeneratePublicgetKeySpec 方法将抛出 InvalidKeySpecException

ML-DSA KeyFactory 使用的编码在 IETF RFC 草案 中定义。我们将跟踪此草案的变化,直到其发布。

替代方案

  • Open Quantum Safe 项目 为他们的 liboqs C 语言库 提供了一个 JNI 封装器,该库实现了一系列抗量子算法,包括 Dilithium 和 ML-DSA。如果 Open Quantum Safe 实现了成为 OpenSSL、BoringSSL、OpenSSH 和 Mozilla 等主要项目的首要抗量子加密实现的目标,那么它将通过广泛的测试和使用获得显著的性能和稳健性提升。

    与原生实现相比,ML-DSA 的 Java 实现提供了直接集成到 JDK 中的关键优势。这使得它立即可以在 JDK 已经移植到的所有平台上使用。

测试

  • 单元测试将确认实现是否符合 KeyGeneratorSignatureKeyFactory API 的规范,包括无效输入参数、边界值和不支持的操作等边缘情况。

  • 已知答案测试(KATs)将涵盖有效的加密操作(正向案例)和无效操作或已知漏洞(负向案例),确保全面验证。这些将包括但不限于:

  • 与其他供应商的实现进行互操作性测试,包括但不限于 liboqs,将确认我们的 ML-DSA 实现能够与其他实现良好协作。