Openssl库之RSA格式解析

Openssl库之RSA格式解析,第1张

Abstract Syntax Notation dot one,抽象语法标记,描述了一种对数据进行表示、传输和解码的数据格式。它提供了一整套正规的格式用于描述对象的结构。它包含两部分:一部分描述信息内数据,数据类型及序列格式;另一部分描述如何将各部分组成消息。而不管语言上如何执行及这些数据的具体指代,也不用去管到底是什么样的应用程序;

ASN1有很多实现版本,Openssl主要采用DER格式,ASN1相关的头文件参见Openssl的源码 asn1.h、asn1t.h,如下所示:

ANS1字段含义:

length —— 管理的数据长度。

type —— 管理的数据类型。

data —— 数据指针。

flags —— 标志位,跟具体数据类型有关

TLV结构即:Type类型, Lenght长度,Value值;它是一种可变格式;Type和Length的长度固定,一般那是2、4个字节;Value的长度由Length指定;

在一段TLV结构描述的数据中例如RSA密钥:

接下来按照TLV格式来分析Openssl所生成的der格式的2048位私钥,这里先说明一下pem格式的密钥和der格式的密钥的区别仅仅在于将der格式的密钥进行base64编码之后加上表头和结尾即为pem格式;

可见私钥当中包含了n、e、d值,所以理论上可以使用私钥进行加密和解密,而在一些加密锁的厂家为了节省内存,会对私钥进行删减,仅仅保留相关解密的参数;

私钥的二进制数据按照TLV结构排列如下:

Openssl查看密钥参数如下:

这里我们大致可以看出TLV结构中的Value和上述过程中的各个参数一致,但是需要说明的是Openssl在查看密钥参数时,已经做了处理保证了modulus、p、q之类有符号位的大数不为负数;所以当我们自己根据这各个参数进行拼接der格式时,具体的方法应当参见上述TLV结构说明;

30 :Type

04A2: 下面内容总长度,超过了0xFF,所以用两个字节描述,所以第二个字节为82,如果下面总长度没有超过0xFF,只用一个字节可以描述,则为81

02:表示asn1_string_st中的type

81:表示长度大于0x80,同时只用一个字节就可以描述

81:参数长度

02:表示asn1_string_st中的type

82:表示长度大于0xFF,需要用两个字节描述

0100:参数长度

02:表示asn1_string_st中的type

03:表示长度是3,小于0x80

1、首先查看/usr/lib64/目录下(如是32位系统那路径就是/usr/lib/)库文件的版本。

2、再查看/usr/lib64/目录下。

3、创建软链接(ln源就是上面查出的对应版本的库文件)。首先执行yumupdateopenssl命令升级openssl版本,然后在安装1.0.1g版本即可,等yum源里有最新的1.0.1g版本,可直接yumupdate到最新。

OpenSSL配置文件采用linux风格,其文件格式由分组字段名、属性名、属性值三部分组成。

如下面的例子:

其中,属性值还支持变量替换,如该例的属性:

log = $path/log

其值最终会被替换为./module_a/log

本文假设你已经安装好了OpenSSL,并且持有一份1.1.1的源码。

配置文件相关的头文件为conf.h、源文件实现在crypto/conf目录中。

这个结构定义了单个配置项的数据结构。主要字段含义:

section —— 表示一个配置段的名称。

name —— 表示在该配置段下的属性名称。

value —— 表示对应属性的值。

这个结构定义了配置抽象方法集合。主要字段含义:

name —— 配置方法名称。

create —— 根据配置抽象方法,创建一个配置项结构,返回其指针。

init —— 初使化配置。

destroy —— 释放所有配置。

destroy_data —— 仅释放所有配置项数据,不释放配置本身。

load_bio —— 以BIO的方式加载配置。

dump —— 打印配置项到BIO中。

is_number —— 判断指定字符是否数字。

to_int —— 将字符转换为数字。

load —— 从文件(重新)加载所有配置。

这个结构定义了配置存储数据结构。主要字段含义:

meth —— 抽象方法集合。

meth_data —— 附加的内存数据,暂时还没有明确用途。

data —— 配置项哈希表。

在1.1.1中,大多数的数据结构已经不再向使用者开放,从封装的角度来看,这是更合理的。如果你在头文件中找不到结构定义,不妨去源码中搜一搜。

CONF *NCONF_new(CONF_METHOD *meth)

指定一个抽象方法集合,创建配置存储结构。

成功返回有效指针,失败返回NULL。

如果meth传入NULL,表示使用默认的抽象方法。

void NCONF_free(CONF *conf)

释放配置存储。

int NCONF_load(CONF *conf, const char *file, long *eline)

从指定文件加载配置,eline表示出错时输出的行号。

成功返回1,失败返回0。

int NCONF_load_bio(CONF *conf, BIO *bp, long *eline)

从BIO加载配置,eline表示出错时输出的行号。

成功返回1,失败返回0。

int NCONF_load_fp(CONF *conf, FILE *fp, long *eline)

NCONF_load_bio()的FILE版本。

char *NCONF_get_string(const CONF *conf, const char *group, const char *name)

从配置中,获取指定分组下的属性值。

成功返回C风格字符串,失败返回NULL。

若group传NULL,表示取全局属性。

int NCONF_get_number_e(const CONF *conf, const char *group, const char *name, long *result)

从配置中,获取指定分组下的数字属性值,数字值输出到result中。

成功返回1,失败返回0。

若group传NULL,表示取全局属性。

STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf, const char *section)

返回指定分组下的配置项堆栈集合。section不能为NULL。

成功返回有效堆栈指针,失败返回NULL。

下面这个例子演示了使用配置API进行基本的文件 *** 作。

test.cnf文件内容:

user = root

[module_a]

path = ./module_a

log = $path/log

filecount = 10

输出:

global user:[root]

module_a::path:[./module_a]

module_a::log:[./module_a/log]

ret:[1] module_a::filecount:[10]

下面这个例子演示了使用BIO读取配置文件,并且遍历指定的分组。

输出:

section:[module_a] name:[path] value:[./module_a]

section:[module_a] name:[log] value:[./module_a/log]

section:[module_a] name:[filecount] value:[10]


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/11732330.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-18
下一篇 2023-05-18

发表评论

登录后才能评论

评论列表(0条)

保存