前言
genkey_main模块,主要用于生成用户私钥和预共享密钥。
启动wg genkey 和 wk genpsk ,都是调用该模块。
源码详解
int genkey_main(int argc, const char *argv[])
{
/*
key(是32个单字节编码的字符数组
*/
uint8_t key[WG_KEY_LEN];
/*
把原始key转换成base64编码的字符串,所以需要在数组最后面加上'/0',长度成了44+1=45.
*/
char base64[((((WG_KEY_LEN) + 2) / 3) * 4 + 1)];
struct stat stat;
if (argc != 1) {
fprintf(stderr, "Usage: %s %s\n", PROG_NAME, argv[0]);
return 1;
}
/*
标准C函数
struct stat,是一个保存文件状态信息的结构体.
文件操作权限的检查。可以Linux 文件操作的C函数库。
*/
if (!fstat(STDOUT_FILENO, &stat) && S_ISREG(stat.st_mode) && stat.st_mode & S_IRWXO)
fputs("Warning: writing to world accessible file.\nConsider setting the umask to 077 and trying again.\n", stderr);
/*
如下是调用系统函数__NR_getrandom,获取32字节随机数key
*/
if (!get_random_bytes(key, WG_KEY_LEN)) {
perror("getrandom");
return 1;
}
/*
如果是生成私钥的指令,需要再将随机数key,转换成curve25519算法处理的key
如果是生成预共享密钥额指令,就不执行curve25519
*/
if (!strcmp(argv[0], "genkey"))
curve25519_clamp_secret(key);
/*
将key编码成base64,函数调用见以下的代码
*/
key_to_base64(base64, key);
puts(base64);
return 0;
}
调用函数
void key_to_base64(char base64[static WG_KEY_LEN_BASE64], const uint8_t key[static WG_KEY_LEN])
{
unsigned int i;
for (i = 0; i < WG_KEY_LEN / 3; ++i)
encode_base64(&base64[i * 4], &key[i * 3]);
encode_base64(&base64[i * 4], (const uint8_t[]){ key[i * 3 + 0], key[i * 3 + 1], 0 });
/*
根据base64的编码规则,32位的原始数据,不是3的整数倍,需要填补一个字节位,这个位置编码为“=”;
也就是base64数字的倒数第二位置,最后补上字符串结尾字符'\0'.
*/
base64[WG_KEY_LEN_BASE64 - 2] = '=';
base64[WG_KEY_LEN_BASE64 - 1] = '\0';
}
备注(1)Base64
1.算法介绍
Base64是一种转换算法,常用于网络传输编码用。要求把3个8位字节(38=24)转化为4个6位的字节(46=24)。
先将三个byte(1byte=8bit)的数据转换为ASCII码二进制值,按序放入一个24bit的缓冲区中。
每次取出6个bit,按照其索引值选择ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
为了保证所输出的编码位可读字符,Base64制定了一个编码表,以便进行统一转换。编码表的大小为2^6=64,这也是Base64名称的由来。
2.举例说明
举个例子:
但是转换到最后你发现不够三个字节了怎么办呢?愿望终于实现了,我们可以用两 个Base64来表示一个字符或用三个Base64表示两个字符,像下图的A对应的第二个Base64的二进制位只有两个,把后边的四个补0就是了。所以 A对应的Base64字符就是QQ。原则是Base64字符的最小单位是四个字符一组,那这才两个字符,后边补两个"=“吧。其实不用”=“也不耽误解码,之所以用”=",可能是考虑到多段编码后的Base64字符串拼起来也不会引起混淆。由此可见 Base64字符串只可能最后出现一个或两个"=",中间是不可能出现"="的。下图中字符"BC"的编码过程也是一样的。
备注(2)Curve 25519
1. 算法简介
Curve25519 是Diffie-Hellman函数,由Daniel J. Bernstein教授设计。
(1) 给定一个用户的32字节私钥(通常通过随机数,再进行变换的方式获得),curve25519计算该私钥对应的公钥(32字节)。
(2) 给定该用户的32字节私钥和其他用户的32字节公钥,curve25519计算出一个32字节的共享密钥供这两个用户使用。然后可以使用这个密钥对两个用户进行身份验证和信息加密。
2.算法使用
更多关于Curve25519的介绍和用法,可参考https://cr.yp.to/ecdh.html
这个地方都是比较老的内容,但是易于大家理解。