公钥-私钥 keypair
签名曲线
账户签名的密码学基于 Ed25519 曲线,Ed25519 是 EdDSA 的一个变种。参考:EdDSA and Ed25519
EdDSA 和 eth 常用的 EcDSA 在签名上有个很重要的区别:
安全性
EdDSA 的安全性设计考虑了抵抗侧信道攻击,它的操作通常是常数时间的,不依赖于输入数据,这降低了泄露私钥的风险。
ECDSA 的安全性取决于其实现的质量;特别是,它需要一个安全的随机数生成器(RNG)来创建签名中的一个参数。如果随机数生成器受到攻击或实现不当,ECDSA的安全性可能受到威胁。
实现细节
EdDSA 生成的签名是确定性的,对于同一个消息和同一个私钥,它会生成相同的签名。
ECDSA 需要在签名过程中使用一个随机数(通常表示为 'k')。如果 'k' 泄露或可预测,攻击者可能能够推算出私钥。
生成一个 keypair
两种方式:
- 通过 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?
- 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的随机数做私钥。