You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于32字节私钥在Google Tink中生成确定性HPKE密钥对的KeysetHandle?

问题

我希望用Google Tink做公钥加密/私钥解密,选它是因为抽象度高、支持多语言(Android和iOS)。我选定了DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM类型的密钥,用X25519曲线的原因:

  • 是Tink官方推荐的混合加密方案
  • 未采用NIST推荐的曲线

出于灾备需求,我需要确定性生成密钥,已有其他安全层,核心目标是避免数据丢失。我已经控制了私钥生成逻辑,本以为公钥可以由Tink基于私钥通过简单运算生成,但Java里创建HpkePrivateKey必须同时提供公钥和私钥,而且相关API还处于alpha阶段。

我试过用JsonKeysetReader导入自制的JSON密钥,但遇到了密钥数据不符合ProtoBuf格式的模糊错误。就算暂时能用,这种方法也像临时hack,我想要规范的实现方案。

请问怎么基于32字节的原始私钥,导入或生成包含有效HPKE密钥对的KeysetHandle?


解决方案

要基于32字节原始X25519私钥生成合规的KeysetHandle,可以通过Tink的底层ProtoBuf结构和密钥构建API实现,以下是规范步骤:

1. 从原始私钥推导公钥

X25519公钥可由私钥直接推导,使用Tink内置工具类完成:

import com.google.crypto.tink.subtle.X25519;

byte[] rawPrivateKey = ...; // 你的32字节原始私钥
byte[] rawPublicKey = X25519.publicFromPrivate(rawPrivateKey);

2. 构建HPKE密钥的Proto结构

按照Tink的Proto定义,将原始密钥封装为HpkePrivateKey对象:

import com.google.crypto.tink.proto.HpkePrivateKey;
import com.google.crypto.tink.proto.HpkePublicKey;
import com.google.crypto.tink.proto.HpkeParams;
import com.google.crypto.tink.proto.HpkeKdf;
import com.google.crypto.tink.proto.HpkeAead;
import com.google.crypto.tink.proto.HpkeKem;
import com.google.protobuf.ByteString;

// 匹配选定密钥类型的HPKE参数
HpkeParams hpkeParams = HpkeParams.newBuilder()
    .setKem(HpkeKem.DHKEM_X25519)
    .setKdf(HpkeKdf.HKDF_SHA256)
    .setAead(HpkeAead.AES_256_GCM)
    .build();

// 构建公钥Proto
HpkePublicKey hpkePublicKey = HpkePublicKey.newBuilder()
    .setParams(hpkeParams)
    .setPublicKey(ByteString.copyFrom(rawPublicKey))
    .build();

// 构建私钥Proto
HpkePrivateKey hpkePrivateKey = HpkePrivateKey.newBuilder()
    .setParams(hpkeParams)
    .setPrivateKey(ByteString.copyFrom(rawPrivateKey))
    .setPublicKey(hpkePublicKey)
    .build();

3. 封装为KeysetHandle

将构建好的HPKE私钥封装成标准KeysetHandle:

import com.google.crypto.tink.KeysetHandle;
import com.google.crypto.tink.hybrid.HybridConfig;
import com.google.crypto.tink.proto.KeyData;
import com.google.crypto.tink.proto.KeyStatusType;
import com.google.crypto.tink.proto.Keyset;
import com.google.crypto.tink.proto.OutputPrefixType;

// 注册HPKE密钥类型
HybridConfig.register();

// 构建KeyData
KeyData keyData = KeyData.newBuilder()
    .setTypeUrl("type.googleapis.com/google.crypto.tink.HpkePrivateKey")
    .setValue(hpkePrivateKey.toByteString())
    .setKeyMaterialType(KeyData.KeyMaterialType.ASYMMETRIC_PRIVATE)
    .build();

// 构建单个密钥实例
Keyset.Key key = Keyset.Key.newBuilder()
    .setKeyData(keyData)
    .setStatus(KeyStatusType.ENABLED)
    .setKeyId(1) // 自定义唯一密钥ID即可
    .setOutputPrefixType(OutputPrefixType.TINK)
    .build();

// 生成Keyset并转换为KeysetHandle
Keyset keyset = Keyset.newBuilder()
    .addKey(key)
    .setPrimaryKeyId(1)
    .build();

KeysetHandle keysetHandle = KeysetHandle.fromProto(keyset);

关键说明

  • 上述方法基于Tink官方Proto定义和底层API,属于规范实现,并非临时hack
  • 确保使用的Tink版本支持目标密钥类型(建议使用最新稳定版)
  • 若需导出为JSON格式,使用JsonKeysetWriter即可生成符合规范的结构,避免之前的格式错误

内容的提问来源于stack exchange,提问作者Pat Lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 01:08:26