【Miracl密码库】AKE密码分析(Authenticated key exchange)
复制到这里排版有些混乱,可在公众号查看原文。
【Miracl密码库】AKE的实现(ake.cpp)
上一篇已经分析了ake.cpp文件的测试,这一篇继续分析AKE的原理,以及在Miracl密码库上实现的过程。
@misc{cryptoeprint:2002/164,
author = {Mike Scott},
title = {Authenticated ID-based Key Exchange and remote log-in with simple token and PIN number},
howpublished = {Cryptology ePrint Archive, Paper 2002/164},
year = {2002},
note = {\url{https://eprint.iacr.org/2002/164}},
url = {https://eprint.iacr.org/2002/164}
}
下面来分析文章
Authenticated ID-based Key Exchange and remote log-in with simple token and PIN

AKE一般基于token或者密码实现,基于token的方案一般基于昂贵的智能卡,但基于密钥的方案要求通信双方共用一把独一无二的密钥。本文借助磁条卡与PIN设计AKE。
协议方案

密钥的构成包括token中的N和PIN,密钥D本身是一个集合中的大数。

认证方有master secret --> s
H(ID) --> EC
Alice --> (H(ID),EC(A)) 也即Alice有ID在EC上的映射点A
Alice有A和PIN(a)
Alice发送ID到认证方注册,接收认证方返回的A和sA,Alice计算aA,存储A和(s-a)A,通过sA=(s-a)A+aA求出来。在DL问题下,Alice是不能通过sA求出s的。
在这个过程中,Alice用自己的ID在认证方完成注册,得到与ID相关的哈希值A。同时,认证方用密钥s对A进行加密。Alice可以自己选择一个PIN值a,然后计算aA,作为混淆的因子。Alice并没有直接将sA存储在硬件中,而是存储带有PIN的差值(s-a)A,其中a是Alice自己能够记住的PIN值。

需要注意的是,为a设置一个增量,不会影响sA=(s-a)A+aA的验证。
(s + δ)A = (s − α)A + (α + δ)A
这也就意味着,即使攻击者能够产生很多的token,但与Alice拥有的PIN(a)不同,攻击者依然不能区分PIN。
密钥交换协议

认证方生成一个512位的质数p,使得p ≡ 3 mod 4,其中p + 1 = c.r,其中 r 为160位的质数,选择一个合适的哈希函数H,将ID通过哈希函数H映射到EC上,公布公共参数{p,r,H},s为160位的密钥。

对于用户方,需要在认证方注册,注册的时候,提供用户ID。注册之后,用户能够获得认证方提供的token和密钥,其中token为I,密钥为sI。用户在硬件上存储token和(s − ρ)I,其中ρ是用户自己选择的PIN值。
模拟一个密钥交互协议

Alice和Bob分别选择一个随机值,交换双方的ID,哈希对方的ID。
Alice用自己的 αA 映射对方ID的哈希值到EC,Bob同样操作,然后交换
在EC上校验双方ID的哈希值
AKE协议实现分析
【Miracl密码库】AKE的实现(ake.cpp)
上一篇复现了AKE源码,没有对源码进行分析,下面来看AKE实现的过程。
在 ake.cpp 中,实现了5种不同 EC 上的 AKE,以 MR_PAIRING_BLS 为例进行分析。
// #define MR_PAIRING_CP // AES-80 security
// #define AES_SECURITY 80
// #define MR_PAIRING_MNT // AES-80 security
// #define AES_SECURITY 80
// #define MR_PAIRING_BN // AES-128 or AES-192 security
// #define AES_SECURITY 128
// #define AES_SECURITY 192
// #define MR_PAIRING_KSS // AES-192 security
// #define AES_SECURITY 192
#define MR_PAIRING_BLS // AES-256 security
#define AES_SECURITY 256
1、包含 pairing_3.h 头文件,表示用的是 Type 3 pairings。在 pairing_3.h 中,包含相应的头文件和定义相应的常量
#include "ecn.h" // G1
// k=24 BLS curve
#ifdef MR_PAIRING_BLS
#include "ecn4.h" // G2
#include "zzn24.h" // GT
#define WINDOW_SIZE 8 // window size for precomputation
#define G2_TYPE ECn4
#define G2_SUBTYPE ZZn4
#define GT_TYPE ZZn24
#define FROB_TYPE ZZn2
#endif
2、源码分析
// 初始化一个PFC (pairing-friendly curve) 对象 pfc
PFC pfc(AES_SECURITY); // initialise pairing-friendly curve
time_t seed; // 临时变量
G1 Alice,Bob,sA,sB;
G2 B6,Server,sS;
GT res,sp,ap,bp;
Big ss,s,a,b;
time(&seed); // 获得一个时间,作为种子
irand((long)seed); // 以时间作为种子,生成随机数
// 生成一个 Big 类型的随机数作为 TA 的密钥
pfc.random(ss); // TA's super-secret ss
// 将 Server 的信息映射到群 G2 上
cout << "Mapping Server ID to point" << endl;
pfc.hash_and_map(Server,(char *)"Server"); // S = Server = H("")
// 将 Alice 和 Bob 的 ID 都映射到 G1 上
cout << "Mapping Alice & Bob ID's to points" << endl;
pfc.hash_and_map(Alice,(char *)"Alice"); // A = Alice = H("")
pfc.hash_and_map(Bob,(char *)"Robert"); // B = Bob = H("")
cout << "Alice, Bob and the Server visit Trusted Authority" << endl;
// sS = ss * S, sA = ss * A, sB = ss * B
sS=pfc.mult(Server,ss); // G2 mult(const G2&,const Big&);
sA=pfc.mult(Alice,ss); // G1 mult(const G1&,const Big&);
sB=pfc.mult(Bob,ss);
cout << "Alice and Server Key Exchange" << endl;
pfc.random(a); // Alice's random number PIN(a)
pfc.random(s); // Server's random number PIN(s)
// e(S, ss * A)
// Server 的 S 与 Alice 的 sA 在 EC 上的映射
res=pfc.pairing(Server,sA); // GT pairing(const G2&,const G1&);
// 如果配对结果为 0,则表示群的阶数不对
if (!pfc.member(res))
{
cout << "Wrong group order - aborting" << endl;
exit(0);
}
// ap = e(S, ss * A)^a
ap=pfc.power(res,a); // GT power(const GT&,const Big&);
// e(ss * S, A)
res=pfc.pairing(sS,Alice);
if (!pfc.member(res))
{
cout << "Wrong group order - aborting" << endl;
exit(0);
}
// sp = e(ss * S, A)^s
sp=pfc.power(res,s);
// e(ss * S, A)^sa
cout << "Alice Key= " << pfc.hash_to_aes_key(pfc.power(sp,a)) << endl;
// e(S, ss * A)^as
cout << "Server Key= " << pfc.hash_to_aes_key(pfc.power(ap,s)) << endl;
cout << "Bob and Server Key Exchange" << endl;
pfc.random(b); // Bob's random number
pfc.random(s); // Server's random number
res=pfc.pairing(Server,sB);
if (!pfc.member(res))
{
cout << "Wrong group order - aborting" << endl;
exit(0);
}
bp=pfc.power(res,b);
res=pfc.pairing(sS,Bob);
if (!pfc.member(res))
{
cout << "Wrong group order - aborting" << endl;
exit(0);
}
sp=pfc.power(res,s);
cout << "Bob's Key= " << pfc.hash_to_aes_key(pfc.power(sp,b)) << endl;
cout << "Server Key= " << pfc.hash_to_aes_key(pfc.power(bp,s)) << endl;
2-1、初始化一个椭圆曲线
PFC pfc(AES_SECURITY); // initialise pairing-friendly curve
2-2、初始化一个系统密钥ss
time_t seed;
time(&seed);
irand((long)seed);
pfc.random(ss);
2-3、对Server的ID哈希,并对Server的ID的哈希值加密sS = ss * S,Server生成一个PIN值s,用自己的sS与Alice的sA做椭圆曲线上的映射e(ss * S, A)
pfc.hash_and_map(Server,(char *)"Server");
sS=pfc.mult(Server,ss);
pfc.random(s);
res=pfc.pairing(sS,Alice);
2-4、Alice做同样的操作,这个过程中,双方交换了ID
pfc.hash_and_map(Alice,(char *)"Alice");
sA=pfc.mult(Alice,ss);
pfc.random(a);
res=pfc.pairing(Server,sA);
2-5、Server与Alice校验双方的信息
// e(ss * S, A)^sa
cout << "Alice Key= " << pfc.hash_to_aes_key(pfc.power(sp,a)) << endl;
// e(S, ss * A)^as
cout << "Server Key= " << pfc.hash_to_aes_key(pfc.power(ap,s)) << endl;
2-6、Server与Bob完成相同的操作
2-7、测试
% ./ake
Mapping Server ID to point
Mapping Alice & Bob ID's to points
Alice, Bob and the Server visit Trusted Authority
Alice and Server Key Exchange
Alice Key= 586308FF2AAEB5CCFE49E7BAF1DE93A62E0CFCA1F7EC07444116B93812B7EC64
Server Key= 586308FF2AAEB5CCFE49E7BAF1DE93A62E0CFCA1F7EC07444116B93812B7EC64
Bob and Server Key Exchange
Bob's Key= 9240B8A3170C8F830385FEB5065F4D4EE47762D6BEF36C7634D62F3884F3CBE5
Server Key= 9240B8A3170C8F830385FEB5065F4D4EE47762D6BEF36C7634D62F3884F3CBE5
从测试结果可知,Alice与Server的密钥是相同的,Server与Bob的密钥是相同的。
函数说明
1、将一个字符串哈希到群上,H(string)
void hash_and_map(G1&,char *);
void hash_and_map(G2&,char *);
2、群上的元素做乘法运算,sA,A为群上的元素,调用pfc.mult()
G1 mult(const G1&,const Big&);
G2 mult(const G2&,const Big&);
3、生成随机元,调用pfc.random(a)
void random(Big&);
void random(G1&);
void random(G2&);
4、双线性映射,e(A,B),调用pfc.pairing()
GT pairing(const G2&,const G1&);
5、椭圆曲线上点的加法,e(A,B)^x,调用pfc.power()
GT power(const GT&,const Big&);
6、将群上的点映射为哈希值
Big hash_to_aes_key(const GT&);
欢迎留言讨论