(二)wireguard-tools源码解读之genkey_main

文章详细介绍了如何使用genkey_main模块生成用户私钥和预共享密钥,涉及Base64编码和Curve25519算法。通过调用getrandom_bytes获取随机数,再经curve25519_clamp_secret处理生成私钥,最后通过key_to_base64将密钥转换为Base64字符串。此外,还阐述了Base64编码的基本原理和Curve25519的用途。


前言

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
这个地方都是比较老的内容,但是易于大家理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值