RSA学习小记

本文最后更新于$day天前,文中所描述的信息可能已发生改变。

一路以来,接触最多的算法是MD5,SHA1。

或者AES等对称加密。对RSA的加密方式比较少接触。

最近在研究一个算法,需要用到RSA,我发现,使用起来,并没有那么简单。

RSA公开密钥密码体制。所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。

第一、我以前对密钥的理解更新了新的知识

以我之前的理解,RSA算法,需要公钥和私钥,公钥加密、私钥解密。

如果需要反过来,那可以把密钥调换,即可做到互相接收密钥的作用。外部消息通过公钥加密,传输过来,本地使用私钥解密,即可防止中间人攻击,让他们无法修改消息。

如果需要互相传递消息,我们只需要两对密钥,并互相交换即可。

昨天我才知道,原来公钥,是可以通过私钥推理出来。那么私钥其实就成为了整个非常重要的钥匙,是很难进行交换的。

第一种用法:公钥加密,私钥解密。—用于加解密

第二种用法:私钥签名,公钥验签。—用于签名

如果数字证书,按照公钥加密,私钥解密,那么就不可能了,所以原来证书,是反过来的。我们所有电脑都有公钥,用于验证对方计算机签发证书是否正确,而私钥只能储存在证书签发机构。这样才能确保证书的签发安全。

第二、RSA算法、填充方法、也分很多种。

非对称算法,常用有RSA、RSA2、国密算法、 ECDSA - 支付宝开放平台提供的加密方式

①、我们常用的只有:RSA

②、密钥长度常用是:1024、2048

③、填充方式:常用是 PKCS1 Java常用是PKCS8

PKCS的常用方式

第三、公钥、私钥的存在形式

密钥存在形式有已Base64形式存在、二进制HEX形式存在、XML形式存在,证书形式存在

一看,蒙圈了,连证书方式也有那么多种。

①、证书形式和Base64形式其实是一致的,他们可以方便互相转换。证书形式就是多了一个 —–BEGIN PUBLIC KEY—– 形式,介绍这个证书是私钥、公钥还是有密码的私钥。以下提供一个PHP从Base64形式转换成公私钥的代码,原理就是每64位换行

$publicKey = ‘公钥’;
$privateKey = ‘私钥’;
$pubPem = chunk_split($publicKey,64,”\n”);
$pubPem = “—–BEGIN PUBLIC KEY—–\n” . $pubPem . “—–END PUBLIC KEY—–\n”;
print_r($pubPem);
// 验证公钥格式是否正确
$pu_key = openssl_pkey_get_public($pubPem);
if (!$pu_key) die(‘$pu_key 格式不正确’);
$priPem = chunk_split($privateKey,64,”\n”);
$priPem = “—–BEGIN PRIVATE KEY—–\n” . $priPem . “—–END PRIVATE KEY—–\n”;

代码引用-> https://199508.com/post/2052

PHP代码有chunk_split 函数,方便切割。

②、XML形式XML形式主要是C#使用函数FromXmlString 加载密钥使用,公钥存在Modulus中,私钥分为很多形式,我用图片说明。

红色圈的都是C#里面XMLFile的私钥

你必须对私钥、RSA算法理解清楚才知道每个参数作用。兼职灭绝人性,怎么那么不通用呢。

③、二进制形式,由于C#里面都使用Byte[]来存储各个参数而不是Base64代码,所以我们通常是直接把Byte[]转换成Hex进行储存。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
RSA rsa = RSA.Create()
rsa.ImportParameters(new RSAParameters() { Exponent = "010001".ToByteArray(16, 2), Modulus = RsaKey.ToByteArray(16, 2) });
//ToByteArray 函数为 引用:System.Extended.dll
//程序集 System.Extended, Version=3.4.16.616, Culture=neutral, PublicKeyToken=675fb48d7a2b2d96
//用意是把String已16禁止转换成Byte\[\]
//或使用我反编译代码
public static byte\[\] ToByteArray(this string value, int radix, int width)
{
List list = new List();
for (int i = 0; i < value.Length; i += width) { byte? b = (i + width > value.Length) ? value.Substring(i, value.Length - i).ToByte(radix) : value.Substring(i, width).ToByte(radix);
if (!b.HasValue)
{
return null;
}
list.Add(b.Value);
}
return list.ToArray();
}

④、由于他们存在形式太多,如果我们使用在服务器、软件、网页上的证书还有包含信息的证书:CSR、PEM、PFX、JKS、P7B、CRT、CER。

在SSL版本、协议上更为复杂。我们在这里不过多研究。记录下几个常用在线网站及一个C# RSA库,可以方便转换PEM文件导入导出密钥使用。

https://www.myssl.cn/tools - 一个SSL在线工具

https://myssl.com/csr\_create.html –也是一个SSL在线辅助工具

http://tool.chacuo.net/cryptrsapubkey – 一个在线加解密工具

https://www.cnblogs.com/yyl8781697/archive/2013/04/28/RSA.html

整合一个基于c#的RSA私钥加密公钥解密的Helper类,含源码

https://www.cnblogs.com/xiangyuecn/p/9922325.html

C#的RSA加密解密签名,就为了支持PEM PKCS#8格式密钥对的导入导出

第四、小结

在现在中间人攻击猖獗时代,量子计算机还没大规模应用,我们只能使用不同加密手段去保护信息安全,防止泄密、监听、拦截。非对称加密只是其中一种。我们在看酸酸乳软件里面,还有更多复杂而厉害的加密、混淆、欺骗的方式。

而一个RSA算法,用不同密钥形式、不同填充方式、不同密钥长度,参数只要错了一个,就无法使用。导致破解算法和协议时,不仅需要对汇编和动态调试了解,还需要对整个加密体系非常了解,在android的调用方式也需要了解,否则将无法还原加密。

最后,分享多一份C# 使用 私钥 RSA,SHA256,签名的代码,虽然没有验签代码,应该也是一个例子。