rust 将%{v_扩展名}转换为%{v_扩展名}

ippsafx7  于 2023-11-19  发布在  其他
关注(0)|答案(1)|浏览(68)

对于只有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

bvhaajcl

bvhaajcl1#

ed25519_dalek生成的verifying_key()并不是标量在曲线上相乘得到的点,这是因为在真实的Ed 25519中用于签名的秘密密钥不是标量本身,而是在scret标量上进行SHA-512密钥推导的结果,产生32个字节作为新标量,32个字节作为签名的伪随机哈希输入。
为了使签名和验证部分的独立密钥推导工作,需要不同的密钥推导算法,如Signal的XEdDSA规范所述。

相关问题