PAKE,即Password-authenticated key agreement,密码认证秘钥协商。
在密码学中,PAKE是指:
PAKE的一个重要属性是:
这也就意味着可基于弱密码获得强安全性。
PAKE相关算法主要有:
在最严格的只使用密码的安全模型中,以上算法的用户不需要记住密码以外的任何秘密或公共数据。
相关代码实现参见:
平衡PAKE假设双方为client-client或client-server关系,使用相同的密码来协商认证一个共享秘钥。
平衡PAKE的例子主要有:
增强PAKE用于client-server场景,其中server端不存储与密码等效的数据。这就意味着窃取服务器数据的攻击者仍然不能伪装成客户机,除非他们首先密码执行暴力搜索。
一些增强PAKE系统使用 不经意伪随机数函数 将用户的密码和服务端的密码salt值 混合,使得用户永远不知道服务端 的秘密salt值,而服务端也永远不知道用户的密码或最终秘钥。
增强PAKE例子有:
密码认证秘钥检索 是指:
第一个密码认证秘钥检索算法由Ford和Kaliski于2000年提出。
以下内容主要摘自 Andalla等人2015年论文Simple Password-Based Encrypted Key Exchange Protocols。
password-based encrypted key exchange设计为:
不同的秘钥交换协议各有利弊,如SIGMA协议[18]用于 基于签名模式的Internet Key Exchange (IKE)协议中。
Password-based key exchange 协议针对的是更实际的场景,即:
Encrypted key exchange:password-based key exchange领域的开创性工作来自于Bellovin和Merrit[7]的encrypted key exchange (EKE)协议。
尽可能少的使用random oracles。理论上,可如KOY 协议[6] 移除所有的random oracles,但是那样的效率要低于EKE协议。
与SPAKE1相比,将session key的算法修改为:
S K ← H ( A , B , X ∗ , Y ∗ , p w , K ) SK\leftarrow H(A,B,X^*,Y^*,pw,K) SK←H(A,B,X∗,Y∗,pw,K)
这样就支持参与者之间根据不同的秘密并行建立多个session key。
在https://github.com/RustCrypto/PAKEs/blob/master/spake2/src/lib.rs 中对SPAKE2 基于curve25519做了相应的实现。
其中ed25519_hash_to_scalar
将bytes转换为scalar值,使用了 HMAC-based Extract-and-Expand Key Derivation Function (HKDF) 中的sha256算法:
fn ed25519_hash_to_scalar(s: &[u8]) -> c2_Scalar {
//c2_Scalar::hash_from_bytes::(&s)
// spake2.py does:
// h = HKDF(salt=b"", ikm=s, hash=SHA256, info=b"SPAKE2 pw", len=32+16)
// i = int(h, 16)
// i % q
let mut okm = [0u8; 32 + 16];
Hkdf::::new(Some(b""), s)
.expand(b"SPAKE2 pw", &mut okm)
.unwrap();
//println!("expanded: {}{}", "................................", okm.iter().to_hex()); // ok
let mut reducible = [0u8; 64]; // little-endian
for (i, x) in okm.iter().enumerate().take(32 + 16) {
reducible[32 + 16 - 1 - i] = *x;
}
//println!("reducible: {}", reducible.iter().to_hex());
c2_Scalar::from_bytes_mod_order_wide(&reducible)
//let reduced = c2_Scalar::reduce(&reducible);
//println!("reduced: {}", reduced.as_bytes().to_hex());
//println!("done");
//reduced
}
详细SPAKE2示例为:
// we implement a custom Debug below, to avoid revealing secrets in a dump
#[derive(PartialEq, Eq)]
pub struct SPAKE2 {
//where &G::Scalar: Neg {
side: Side,
xy_scalar: G::Scalar,
password_vec: Vec,
id_a: Vec,
id_b: Vec,
id_s: Vec,
msg1: Vec,
password_scalar: G::Scalar,
}
#[test]
fn test_asymmetric() {
let scalar_a = decimal_to_scalar(
b"2611694063369306139794446498317402240796898290761098242657700742213257926693",
);
let scalar_b = decimal_to_scalar(
b"7002393159576182977806091886122272758628412261510164356026361256515836884383",
);
let expected_pw_scalar = decimal_to_scalar(
b"3515301705789368674385125653994241092664323519848410154015274772661223168839",
);
println!("scalar_a is {}", hex::encode(scalar_a.as_bytes()));
let (s1, msg1) = SPAKE2::::start_a_internal(
&Password::new(b"password"),
&Identity::new(b"idA"),
&Identity::new(b"idB"),
scalar_a,
);
let expected_msg1 = "416fc960df73c9cf8ed7198b0c9534e2e96a5984bfc5edc023fd24dacf371f2af9";
println!();
println!("xys1: {:?}", hex::encode(s1.xy_scalar.as_bytes()));
println!();
println!("pws1: {:?}", hex::encode(s1.password_scalar.as_bytes()));
println!("exp : {:?}", hex::encode(expected_pw_scalar.as_bytes()));
println!();
println!("msg1: {:?}", hex::encode(&msg1));
println!("exp : {:?}", expected_msg1);
println!();
assert_eq!(
hex::encode(expected_pw_scalar.as_bytes()),
hex::encode(s1.password_scalar.as_bytes())
);
assert_eq!(hex::encode(&msg1), expected_msg1);
let (s2, msg2) = SPAKE2::::start_b_internal(
&Password::new(b"password"),
&Identity::new(b"idA"),
&Identity::new(b"idB"),
scalar_b,
);
assert_eq!(expected_pw_scalar, s2.password_scalar);
assert_eq!(
hex::encode(&msg2),
"42354e97b88406922b1df4bea1d7870f17aed3dba7c720b313edae315b00959309"
);
let key1 = s1.finish(&msg2).unwrap();
let key2 = s2.finish(&msg1).unwrap();
assert_eq!(key1, key2);
assert_eq!(
hex::encode(key1),
"712295de7219c675ddd31942184aa26e0a957cf216bc230d165b215047b520c1"
);
}
[1] Wikipedia Password-authenticated key agreement
[2] Andalla等人2015年论文Simple Password-Based Encrypted Key Exchange Protocols
[3] SPAKE2, a PAKE draft