对于只有X25519密钥对可用但我需要使用现有密钥创建和验证签名的场景,我尝试将X25519公钥转换为Ed25519验证密钥,该密钥可以成功验证使用X25519私钥创建的签名。
虽然一般不赞成(我知道原因,但正如所述,X25519密钥对是我的全部),但在野外有一个实现,available as C code。
由于周围的软件使用dalek crate集,我也使用这个库来进行转换。我的公钥转换函数如下:
pub(crate) fn x25519_pub_to_ed25519_ver(
public_key: [u8; 32],
) -> Result<VerifyingKey, SignatureError> {
match MontgomeryPoint(public_key).to_edwards(SIGN_BIT) {
None => Err(SignatureError::new()),
Some(key) => VerifyingKey::from_bytes(key.compress().as_bytes()),
}
}
字符串
这将从蒙哥马利点计算爱德华兹点,我已经验证了to_edwards代码的功能与上面的参考代码linekd的功能完全相同。
对于签名方,我认为我需要确保使用一个私钥,这将产生正确的签名,因为X25519和Ed25519公钥之间的转换不是1:1。我的参考库也有一个如何产生匹配私钥的示例,我试图模仿:
pub(crate) fn x25519_priv_to_ed25519_sig(private_key: &StaticSecret) -> SigningKey {
let clamped = clamp_integer(private_key.to_bytes());
let signing_key = SigningKey::from_bytes(&clamped);
let test_public_key = signing_key.verifying_key().to_bytes();
if (test_public_key[31] & 0x80) >> 7 == SIGN_BIT {
signing_key
} else {
let scalar = Scalar::from_bytes_mod_order(clamped);
let neg = scalar.invert();
SigningKey::from_bytes(&neg.to_bytes())
}
}
型
不幸的是,我的测试代码不起作用,生成的公钥与直接从计算的Ed25519密钥导出的Ed25519验证密钥不匹配:
const TEST_MESSAGE: &[u8] = b"Das Pferd frisst keinen Gurkensalat.";
fn main() {
let private_key = StaticSecret::random();
println!("X25519 private key: {:02x?}", private_key.to_bytes());
let public_key = PublicKey::from(&private_key);
let signing_key = x25519_priv_to_ed25519_sig(&private_key);
println!("Ed25519 signing key: {:02x?}", signing_key.to_bytes());
let signature = signing_key.sign(TEST_MESSAGE);
let verifying_key = x25519_pub_to_ed25519_ver(public_key.to_bytes()).unwrap();
println!(
"Transformed verifying key: {:02x?}",
verifying_key.to_bytes()
);
println!(
"Real verifying key: {:02x?}",
signing_key.verifying_key().to_bytes()
);
let result = verifying_key.verify(TEST_MESSAGE, &signature);
assert!(result.is_ok());
}
型
在哪一点上我做的转换是错误的?
一个可以用cargo
运行的最小工作示例可以是found on Codeberg。
1条答案
按热度按时间bvhaajcl1#
由
ed25519_dalek
生成的verifying_key()
并不是标量在曲线上相乘得到的点,这是因为在真实的Ed 25519中用于签名的秘密密钥不是标量本身,而是在scret标量上进行SHA-512密钥推导的结果,产生32个字节作为新标量,32个字节作为签名的伪随机哈希输入。为了使签名和验证部分的独立密钥推导工作,需要不同的密钥推导算法,如Signal的XEdDSA规范所述。