OpenSSL中RSA算法指令主要有三个:
genrsa
生成RSA密钥
rsa
处理RSA密钥的格式转换等问题
rsautl
使用RSA密钥进行加密、解密、签名和验证等运算
1.生成RSA密钥命令
$ openssl genrsa –out
rsa2048.pem 2048
-out 指定生成文件,包含公钥和私钥。
注:OpenSSL 1.0.1f 6 Jan
2014 默认以PKCS#1
RSAPrivateKey结构标准输出。
PEM私钥格式文件:
-----BEGIN
RSA PRIVATE KEY-----
BASE64私钥内容
-----END
RSA PRIVATE KEY-----
二进制格式文件解析:
2048
1024
标签头:3082
标签头:3082
长
度:04a4 即后接1188字节数据
长
度:0278 即后接632字节数据
版
本:020100
版 本:020100
02 -
tag
01 -
length
00 -
value
RSA_N:02820101 + 00 +
data
RSA_N:028181 + 00 + data
02 -
tag
82 -
81代表长度用1字节表示,82代表长度用2字节表示
0101 -
长度,257字节
81 - 长度,129字节
00 -
未知
RSA_D
: 02820101 + 00 + data
RSA_D :
028181 + 00 + data
RSA_p
: 028181 + 00 + data
RSA_P : 028141 + 00 +
data
RSA_q
: 028181 + 00 + data
RSA_q : 028141 + 00 +
data
RSA_E
:0203010001
RSA_E :0203010001
02 -
tag
03 -
length
010001 -
value 65537
-----------------------------------------------------------------------------------------------------------------
2.提取PEM格式RSA公钥命令
$ openssl rsa –in
rsa2048.pem –pubout –out rsa2048_pub.pem
注:OpenSSL
1.0.1f 6 Jan 2014 默认以SubjectPublicKeyInfo结构标准输出。
PEM公钥格式文件:
-----BEGIN
PUBLIC KEY-----
BASE64公钥内容
-----END
PUBLIC KEY-----
二进制格式文件解析:以2048为例
标签头:3082
长
度:010a 即后接266字节数据
--->实际为0122300d06092a864886f70d01010105000382010f003082010a
其中24字节数据估计为 const RSA_METHOD
*meth;
ENGINE *engine;
RSA_N:02820101 + 00 +
data
02 -
tag
82 -
81代表长度用1字节表示,82代表长度用2字节表示
0101 -
长度,257字节
81 - 长度,129字节
00 -
未知
RSA_E :0203010001
02 -
tag
03 -
length
010001 -
value 65537
公钥读取函数:
RSA *PEM_read_RSA_PUBKEY(file, NULL, NULL,
NULL)) 如果公钥类型不是RSA,返回读取失败信息。
-----------------------------------------------------------------------------------------------------------------
3.提取PEM RSAPublicKey格式公钥命令
$ openssl rsa –in
rsa2048.pem –RSAPublicKey_out –out rsa2048_public.pem
注:OpenSSL 1.0.1f 6 Jan
2014 以PKCS#1 RSAPublicKey 结构标准输出。
-----BEGIN
RSA PUBLIC KEY-----
BASE64公钥内容
-----END RSA
PUBLIC KEY-----
二进制格式文件解析:
2048
1024
标签头:3082
标签头:3082
长
度:010a 即后接266字节数据
长 度:
RSA_N:02820101 + 00 +
data
RSA_N:028181 + 00 + data
02 -
tag
82 -
81代表长度用1字节表示,82代表长度用2字节表示
0101 -
长度,257字节
81 - 长度,129字节
00 -
未知
RSA_E
:0203010001
RSA_E :0203010001
02 -
tag
03 -
length
010001 -
value 65537
公钥读取函数:
RSA *PEM_read_RSAPublicKey(FILE
*fp, RSA **x,pem_password_cb *cb, void *u);
-----------------------------------------------------------------------------------------------------------------
4.生成的RSA
公/私钥文件为base64编码,将其转换成二进制编码
//base64转换成16进制格式
$ openssl base64 –d –in
base64.txt –out hex.txt
$ openssl base64 –d –in
rsa2048.pem –out rsa2048.bin
//16进制转换成base64格式
$ openssl base64 –in
hex.txt –out base64.txt
5.明文形式输出密钥的各个参数值
$ openssl rsa –in rsa2048.pem –text –out
rsa2048.txt
-----------------------------------------------------------------------------------------------------------------
6.RSA密钥语法
在PKCS#1 RSA算法标准中,定义RSA私钥语法为:
RSAPrivateKey ::= SEQUENCE {
version
Version,
版本号 默认为0,使用多素数为1
modulus
INTEGER,
--n
RSA的合数模n=p*q
publicExponent
INTEGER, --e
RSA的公开幂e
privateExponent INTEGER,
--d
RSA的私有幂d
prime1
INTEGER,
--p
n的素数因子p
prime2
INTEGER,
--q
n的素数因子q
exponent1
INTEGER,
--d mod
(p-1)
exponent2
INTEGER,
--d mod (q-1)
coefficient
INTEGER,
--(inverse of q) mod
p CRT系数q-1
mod p
otherPrimeInfos
OtherPrimeInfos OPTIONAL
使用此项,版本号为1。
}
otherPrimeInfos ::= SEQUENCE {
prime
INTEGER,
--ri
n的一个素数因子,其中i>=3。
exponent
INTEGER,
--di di = d mod (ri - 1)
coefficient
INTEGER --ti
CRT系数 ti = (r1 * r2 * ... * ri-1)-1 mod ri
}
公钥语法为:
RSAPublicKey ::= SEQUENCE {
modulus
INTEGER,
--n
RSA的合数模n
publicExponent
INTEGER --e
RSA的公开幂
}
-----------------------------------------------------------------------------------------------------------------
rsautl指令说明
RSA每次能够加密的数据长度不能超过RSA密钥长度,并且根据具体的补齐方式不同输入的加密数据最大长度也不一样,而输出长度则总是跟RSA密钥长度相等。
数据补齐方式
输入数据长度
输出数据长度
参数字符串
填充方式宏定义
PKCS#1 v1.5(默认)
小于(密钥长度-11)字节
同密钥长度
-pkcs
RSA_PKCS1_PADDING 1
PKCS#1
OAEP
小于(密钥长度-11)字节
同密钥长度
-oaep RSA_PKCS1_OAEP_PADDING 4
PKCS#1 for SSLv23
小于(密钥长度-11)字节
同密钥长度
-ssl
不使用补齐
同密钥长度
同密钥长度
-raw
RSA_NO_PADDING 3
7.RSA公钥加密
//使用RSA公钥加密
$ openssl rsautl
-encrypt -in plain.txt -inkey pub.pem -pubin -out enc.txt
-pubin 指定输入的是RSA公钥
-certin 指定输入的是证书文件
//使用RSA密钥加密,实际上使用其中的公钥加密
$ openssl rsautl
-encrypt -in plain.txt -inkey RSA.pem -out enc.txt
8.RSA私钥解密
//使用RSA密钥解密,实际上使用其中的私钥解密
$ openssl rsautl
-decrypt -in enc.txt -inkey RSA.pem -out replain.txt
$ diff plain.txt
replain.txt
//比较原始文件和解密后文件
9.RSA私钥签名
//使用RSA密钥签名,实际上使用其中的私钥加密
$ openssl rsautl -sign
-in plain.txt -inkey RSA.pem -out sign.txt
//提取PCKS8格式的私钥
$ openssl pkcs8 -topk8
-in RSA.pem -out pri.pem -nocrypt
//使用RSA私钥签名
$ openssl rsautl -sign
-in plain.txt -inkey pri.pem -out sign.txt
-------------------------------------------------------------------------------------------------
注意:开发代码与Linux
openssl签名结果比较验证时需注意!
签名输入文件-in
plain.txt,openssl读取以16进制格式读取输入。
新建文件,输入16进制数据文本,并不是openssl签名的16进制数据。
通过open
write函数,写入16进制数据到文件才是纯16进制文件。
Android.mk -->生成可执行模块 LOCAL_MODULE :=
sign
.c文件:要包含openssl相关头文件
int signimg(char *in, char *out, char *key_path)
{
int i;
int fd = 0;
int hash_data_len = 36;
//test hash_data len
char *key[2] = { 0 };
char *hash_data = NULL; //哈希文件指针
char *hash_sign = NULL;
//签名文件
char data[256];
uint8_t signature[256];
for(i=0;i<256;i++) //赋值
data[i]=i+6;
hash_data = in;
hash_sign = out;
printf("input image name is:%s\n",in);
for (i = 0; i < 2; i++) {
key[i] = (char *)malloc(NAME_MAX_LEN);
if (key[i] == 0)
goto fail;
memset(key[i], 0, NAME_MAX_LEN);
strcpy(key[i], key_path);
if (key_path[strlen(key_path) - 1] != '\/')
key[i][strlen(key_path)] = '/';
}
strcat(key[0], "rsa2048_0.pem");
strcat(key[1], "rsa2048_1.pem");
fd = open(hash_data, O_CREAT | O_TRUNC | O_WRONLY, 0644);
//打开哈希文件
if (fd == 0) {
printf("error:could create '%s'\n", hash_data);
return 0;
}
if (write(fd, data, hash_data_len) !=
hash_data_len)
//哈希文件,写入16进制数据
goto fail;
// unlink(hash_data);
//删除哈希文件
close(fd);
一般无上面操作,直接读取16进制文件
input_data = load_file(img,
&img_len);
if (input_data == 0) {
printf("error:could not load
img\n");
return 0;
}
printf("img_len = %d\n",
img_len);
calcSignature(data, hash_data_len, signature,
key[0]); //签名运算
printf("signature: ");
for(i=0;i<256;i++)
printf("x",signature[i]);
//打印签名
printf("\n");
fd = open(hash_sign, O_CREAT | O_TRUNC | O_WRONLY, 0644);
//打开签名文件
if (fd == 0) {
printf("error:could create '%s'\n", hash_sign);
return 0;
}
if (write(fd, signature, 256) != 256)
//写入签名结果
goto fail;
// unlink(hash_sign); //删除签名文件
close(fd);
printf("---------------------------------------------------------------\n");
return 1;
fail:
printf("sign failed!!!\n");
for (i = 0; i < 2; i++) {
if (key[i] != 0)
free(key[i]);
}
return 0;
}
int main(int argc, char **argv)
{
if (argc != 4) {
usage();
return 0;
}
char *cmd1 = argv[1]; //hash_data.bin
char *cmd2 = argv[2]; //hash_sign.bin
char *cmd3 = argv[3]; //key documount
sprd_signimg(cmd1, cmd2, cmd3);
}
.sh脚本文件
#!/bin/sh
HOST_OUT=$CURPATH/out/host/linux-x86/bin
//可执行模块路径
CFGPATH=$(pwd)
//当前路径
HASH_DATA=$(pwd)/hash_data.bin
HASH_DATA_SIGNED=$(pwd)/hash_sign.bin
doSign()
{
$HOST_OUT/sign
$HASH_DATA $HASH_DATA_SIGNED $CFGPATH
}
doSign "$@"
-------------------------------------------------------------------------------------------------
10.RSA公钥验签
//使用RSA密钥验证,实际上使用其中的公钥解密
$ openssl rsautl -verify
-in sign.txt -inkey RSA.pem -out replain.txt
//使用RSA公钥验证
$ openssl rsautl -verify
-in sign.txt -inkey pub.pem -pubin -out replain.txt
//比较原始文件和签名解密后文件
$ diff plain.txt
replain.txt
注:相同明文,相同密钥加密/签名后的密文结果不一样?
是因为填充模式中要填充随机数,导致每次加密结果不同。
相同明文,相同密钥,默认的-pkcs填充格式每次签名结果是一样的。
-----------------------------------------------------------------------------------------------------------------
附:rsa1024密钥各参数
Private-Key: (1024 bit) (大端模式)
modulus:
00:aa:cd:56:35:d5:00:2d:12:dd:cd:10:85:39:0c:
f8:61:70:08:5d:a1:a0:d3:6b:50:34:85:b8:db:19:
f5:0a:b5:29:f6:0d:f8:e4:1c:a8:b4:24:bf:ac:13:
c3:c3:47:75:a2:23:74:56:4d:b9:b1:50:e7:5e:21:
82:c3:80:39:c9:6e:9d:1f:2c:33:59:39:cd:f3:69:
dc:11:84:a3:5c:4e:c8:3a:ca:e7:a2:6f:68:39:ea:
b9:ad:86:c5:de:0c:6c:a4:8a:0c:aa:d6:29:f8:20:
94:84:91:0a:2c:98:65:05:c6:d1:d4:68:db:5a:01:
67:5a:66:d8:4e:a4:ce:2f:bd
publicExponent: 65537 (0x10001)
privateExponent:
00:8d:0e:bf:9f:fd:a5:03:94:8d:31:09:ef:bc:4a:
05:e7:12:8b:16:28:a1:95:79:0e:e8:11:77:b5:1b:
1e:d0:15:05:ee:7b:63:8d:a0:4d:83:58:c6:22:ea:
bf:c5:ca:82:4f:c1:50:16:e6:61:f1:1a:8b:b9:a5:
9b:44:b1:e5:06:28:72:43:61:32:5e:47:bc:a8:09:
06:62:90:7e:81:d4:65:32:1e:ba:34:5a:74:39:45:
f1:db:64:69:7c:c0:e5:57:73:64:a7:ca:10:51:77:
20:43:bb:6d:ef:10:13:93:e7:39:9f:47:2d:9d:f4:
d9:4c:8a:23:c1:62:00:c9:01
prime1:
00:d9:df:2e:58:91:eb:34:57:e3:c3:36:b7:56:eb:
4a:6d:92:82:8c:4f:c9:97:54:2f:ec:f6:18:95:93:
12:4e:25:81:94:6d:8c:46:bf:e9:19:c3:1a:0a:b2:
2e:94:95:a6:51:57:7b:0e:1c:e9:9a:5d:a0:7b:3f:
61:3a:60:cb:ed
prime2:
00:c8:b1:65:dd:89:40:cb:31:af:e4:2d:fd:af:b5:
c0:2b:e8:a1:33:6d:d9:9d:dc:35:75:43:87:36:fd:
05:66:10:af:3e:84:99:1b:a5:2f:36:1b:d0:24:98:
fc:e8:75:77:a9:a1:bf:1e:67:c3:6d:b8:58:ca:47:
59:44:80:99:11
exponent1:
63:a9:97:0e:c6:f9:1b:c1:94:9b:a8:fc:e7:12:cc:
c2:20:c1:fd:23:46:69:26:06:a2:53:d4:dd:1f:20:
c1:84:a0:a8:e0:0f:ca:11:61:b4:fa:2d:80:75:0f:
9f:c2:71:09:46:86:30:e7:82:e8:ad:29:8b:17:6c:
07:83:5d:e5
exponent2:
00:89:cc:bc:bb:e3:4d:18:f7:d1:e4:e3:eb:47:65:
8d:40:d8:e7:2e:8f:e3:97:2f:a7:89:0f:c7:dc:ea:
d8:75:1f:49:a4:ac:99:10:51:58:5c:57:b6:90:1a:
77:b5:09:4b:13:af:5a:b1:fe:df:42:0c:0c:f3:3f:
10:3d:27:eb:71
coefficient:
00:96:02:a5:9d:e3:c1:77:89:2b:6a:71:44:51:9a:
ad:57:b1:65:c6:a9:45:21:c3:7b:66:e6:da:18:ad:
64:ff:29:a8:50:a0:3e:1e:1e:e9:7a:1c:bb:ec:a6:
ef:d3:23:8b:54:43:5a:e3:75:c8:9e:ba:33:27:a5:
9e:eb:36:34:d4
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQCqzVY11QAtEt3NEIU5DPhhcAhdoaDTa1A0hbjbGfUKtSn2Dfjk
HKi0JL+sE8PDR3WiI3RWTbmxUOdeIYLDgDnJbp0fLDNZOc3zadwRhKNcTsg6yuei
b2g56rmthsXeDGykigyq1in4IJSEkQosmGUFxtHUaNtaAWdaZthOpM4vvQIDAQAB
AoGBAI0Ov5/9pQOUjTEJ77xKBecSixYooZV5DugRd7UbHtAVBe57Y42gTYNYxiLq
v8XKgk/BUBbmYfEai7mlm0Sx5QYockNhMl5HvKgJBmKQfoHUZTIeujRadDlF8dtk
aXzA5VdzZKfKEFF3IEO7be8QE5PnOZ9HLZ302UyKI8FiAMkBAkEA2d8uWJHrNFfj
wza3VutKbZKCjE/Jl1Qv7PYYlZMSTiWBlG2MRr/pGcMaCrIulJWmUVd7Dhzpml2g
ez9hOmDL7QJBAMixZd2JQMsxr+Qt/a+1wCvooTNt2Z3cNXVDhzb9BWYQrz6EmRul
LzYb0CSY/Oh1d6mhvx5nw224WMpHWUSAmRECQGOplw7G+RvBlJuo/OcSzMIgwf0j
RmkmBqJT1N0fIMGEoKjgD8oRYbT6LYB1D5/CcQlGhjDnguitKYsXbAeDXeUCQQCJ
zLy7400Y99Hk4+tHZY1A2Ocuj+OXL6eJD8fc6th1H0mkrJkQUVhcV7aQGne1CUsT
r1qx/t9CDAzzPxA9J+txAkEAlgKlnePBd4kranFEUZqtV7FlxqlFIcN7ZubaGK1k
/ymoUKA+Hh7pehy77Kbv0yOLVENa43XInrozJ6We6zY01A==
-----END RSA PRIVATE KEY-----
参考:
1.http://blog.sina.com.cn/s/blog_4fcd1ea30100yh4s.html
2.http://www.qmailer.net/archives/216.html
3.https://www.cnblogs.com/gordon0918/p/5363466.html
加载中,请稍候......