Skip to content

密钥编码

在工作中,会进行密钥的存储和转移。常见地,密钥的存在方式如一个文件,又或者是一个16进制字符串。

本文主要探究ECC密钥的16进制字符串是如何组成的。

使用CryptoPP,生成secp256r1公私钥如下:

bash
# 私钥
0x3041020100301306072a8648ce3d020106082a8648ce3d030107042730250201010420f8db9ea423c6a38c726aa0c3ac912ffcac2fcafe9446471550e61912777c213b
# 公钥
0x3059301306072a8648ce3d020106082a8648ce3d03010703420004e690c566c5d4bcdc484183edd8bd80d4174d33d9a1c9ffe45030334c4e8ce796dd76982a408f7a36386a1196b4c0b97da968977d1790a2d888fa1b9e862c2c85

私钥

bash
# 私钥
0x3041020100301306072a8648ce3d020106082a8648ce3d030107042730250201010420f8db9ea423c6a38c726aa0c3ac912ffcac2fcafe9446471550e61912777c213b

私钥有134个字符,其中前70个字符是密钥的一些参数,后64个字符才是真正的私钥内容。也就是说,多次生成secp256r1私钥,得到的所有私钥的前70个字符都是相同的。

前70个字符

bash
3041020100301306072a8648ce3d020106082a8648ce3d030107042730250201010420

可以将这70个字符拆分如下:

30 41 # 一个DER编码的结构的开始,后续有0x41字节(65字节)内容
	02 01 # 接下来的内容是一个整数,内容的长度为1字节
		00 # 整数的值为0
	30 13 # 一个DER编码的结构的开始,后续有0x13字节(19字节)内容
		06 07 # 一个对象标识符(OID)的结构的开始,内容的长度为7字节
			2a8648ce3d0201 # 定义加密方法,1.2.840.10045.2.1 (ecPublicKey)
		06 08 # 一个对象标识符(OID)的结构的开始,内容的长度为8字节
			2a8648ce3d030107 # 定义曲线类型,1.2.840.10045.3.1.7 (prime256v1),曲线参数
		04 27 # 一个EC Private Key编码的结构的开始,后续有0x27字节(39字节)内容
			30 25 # 一个DER编码的结构的开始,后续有0x25字节(37字节)内容
				02 01 # 接下来的内容是一个整数,内容的长度为1字节,这里是版本号
					01 # 整数的值为1
					04 20 # 一个EC Private Key编码的结构的开始,后续有0x20字节(32字节)内容
					... # 后续内容便是32字节/64个字符/256比特的私钥内容

后64个字符

f8db9ea423c6a38c726aa0c3ac912ffcac2fcafe9446471550e61912777c213b

一个随机数。

公钥

# 公钥
0x3059301306072a8648ce3d020106082a8648ce3d03010703420004e690c566c5d4bcdc484183edd8bd80d4174d33d9a1c9ffe45030334c4e8ce796dd76982a408f7a36386a1196b4c0b97da968977d1790a2d888fa1b9e862c2c85

公钥有182个字符,其中前54个字符是密钥的一些参数,后128个字符才是真正的公钥内容。也就是说,多次生成secp256r1公钥,得到的所有公钥的前54个字符都是相同的。

前54个字符

3059301306072a8648ce3d020106082a8648ce3d03010703420004

可以将这54个字符拆分如下:

30 59 # 一个DER编码的结构的开始,后续有0x59字节(89字节)内容
	30 13 # 一个DER编码的结构的开始,后续有0x13字节(19字节)内容
		06 07 # 一个对象标识符(OID)的结构的开始,内容的长度为7字节
			2a8648ce3d0201 # 定义加密方法,1.2.840.10045.2.1 (ecPublicKey)
		06 08 # 一个对象标识符(OID)的结构的开始,内容的长度为8字节
			2a8648ce3d030107 # 定义曲线类型,1.2.840.10045.3.1.7 (prime256v1),曲线参数
		03 42 # 一个比特流的开始,后续有0x42字节(66字节)内容
			00 04 # 前两个00不知道啥意思,后面的04代表这是未被压缩的公钥
			...	 # 后续内容便是128个字符的公钥内容,是一个坐标点X和Y。X和Y各占64个字符。

后128个字符

e690c566c5d4bcdc484183edd8bd80d4174d33d9a1c9ffe45030334c4e8ce796dd76982a408f7a36386a1196b4c0b97da968977d1790a2d888fa1b9e862c2c85

椭圆曲线上的一个点,由两个64个字符的X和Y组成。

注意

secp256r1 和 prime256v1 都是椭圆曲线加密算法中的曲线名称,也被称为 NIST P-256。这两个名称实际上指代的是同一条椭圆曲线,只是命名方式不同。

  • secp256r1:这个名称中的 "sec" 表示 "Standards for Efficient Cryptography"(高效密码学标准),"p" 表示 "prime field"(素域),"256" 表示使用了 256 位的二进制数字来表示该素域上的坐标,"r1" 表示是该素域上的第一条曲线。
  • prime256v1:这个名称中的 "prime" 表示使用素数域,"256" 表示使用了 256 位的二进制数字来表示该素域上的坐标,"v1" 表示是该素域上的第一条曲线。

参考链接