Skip to main content

公钥-私钥 keypair

签名曲线

账户签名的密码学基于 Ed25519 曲线,Ed25519 是 EdDSA 的一个变种。参考:EdDSA and Ed25519

EdDSA 和 eth 常用的 EcDSA 在签名上有个很重要的区别:

安全性

EdDSA 的安全性设计考虑了抵抗侧信道攻击,它的操作通常是常数时间的,不依赖于输入数据,这降低了泄露私钥的风险。

ECDSA 的安全性取决于其实现的质量;特别是,它需要一个安全的随机数生成器(RNG)来创建签名中的一个参数。如果随机数生成器受到攻击或实现不当,ECDSA的安全性可能受到威胁。

实现细节

EdDSA 生成的签名是确定性的,对于同一个消息和同一个私钥,它会生成相同的签名。

ECDSA 需要在签名过程中使用一个随机数(通常表示为 'k')。如果 'k' 泄露或可预测,攻击者可能能够推算出私钥。

生成一个 keypair

两种方式:

  1. 通过 solana cli :
> solana-keygen new --no-bip39-passphrase  -o 123.json
Generating a new keypair
Wrote new keypair to 123.json
=============================================================================
pubkey: 25itPzJtM2oukNKsBavQ7cJQAaYzYgVpuBrG8cY67DnS
=============================================================================
Save this seed phrase to recover your new keypair:
apart result secret come noise ginger strategy acoustic slam catch olive acid
=============================================================================

你可以在 https://github.com/solana-labs/solana/tree/master/keygen找到源码,大体过程如下:

这里的 private key 其实长度可以不固定,它是由随机的 Mnemonic 派生而来,然后经过 SHA-512 HMAC

pbkdf2::pbkdf2::<Hmac<sha2::Sha512>>(input, salt.as_bytes(), PBKDF2_ROUNDS, &mut seed); 和裁剪,

我们才得到真正的 32字节 private key。是的,Ed25519 签名的私钥就是 32 字节。

看下生成的 123.json 内容:

[40,250,194,125,38,188,154,65,108,78,67,7,74,38,4,53,24,235,184,136,220,36,171,34,120,111,141,169,10,88,69,213,16,17,94,248,81,171,96,197,4,57,15,205,125,99,151,236,14,181,140,97,32,160,176,190,77,159,214,87,91,174,73,219]

64个字节组成的数组,其实前 32 个字节是 private key,后 32 个字节 做 base58 后:

In [310]: import base58

In [311]: base58.b58encode(bytes(a)[:32])
Out[311]: b'25itPzJtM2oukNKsBavQ7cJQAaYzYgVpuBrG8cY67DnS' <--- 与上面打印的公钥相同

参考: How do Ethereum and Solana Generate Public and Private keys?

  1. solana-sdk Keypair::generate
let mut rng = OsRng::default();
ed25519_dalek::Keypair::generate(csprng)

let mut sk: SecretKey = SecretKey([0u8; 32]);
csprng.fill_bytes(&mut sk.0);

非常简单,就是用 OsRng 生成了一个 32 bytes的随机数做私钥。