1.RSA介绍
RSA是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对
其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥,即公钥,而两个大素数组合成私钥。公钥是可发布的供任何人使用,
私钥则为自己所有,供解密之用。解密者拥有私钥,并且将由私钥计算生成的公钥发布给加密者。加密都使用公钥进行加密,并将密文发送
到解密者,解密者用私钥解密将密文解码为明文。
以甲要把信息发给乙为例,首先确定角色:甲为加密者,乙为解密者。首先由乙随机确定一个KEY,称之为密匙,将这个KEY始终保
存在机器B中而不发出来;然后,由这个 KEY计算出另一个KEY,称之为公匙。这个公钥的特性是几乎不可能通过它自身计算出生成它的私钥。
接下来通过网络把这个公钥传给甲,甲收到公钥后,利用公钥对信息加密,并把密文通过网络发送到乙,最后乙利用已知的私钥,就对密文进
行解码了。以上就是RSA算法的工作流程。
2.生成签名与验签流程
生成签名方:首先对参数放入一个字符串数组signFields,把参数和值放入一个对象或map中,使用JSONObject把这个对象转化成json对象。
然后构建签名原文,在构建签名原文时,我们需把参数按照字典(比如a,b,c)顺序排序,具体排序方法直接调java的Arrays.sort方法。 然后使用RSA
的私钥对签名原文进行签名。
验签方:和生产签名方一样先生成签名原文,然后使用RSA的公钥、生成签名方传入的签名及签名原文对生成签名方传入的签名进行验证,验
证结果为true说明验证成功,否则为未通过。
RSA签名校验
-spec check_rsa_sign(DataBin, Sign, RSAPublicKeyBin, DigestType) -> boolean when DataBin :: binary(), Sign :: binary(), RSAPublicKeyBin :: binary() DigestType :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'. check_rsa_sign(DataBin, Sign, RSAPublicKeyBin, DigestType) -> PemEntries = public_key:pem_decode(RSAPublicKeyBin), RSAPubKey = public_key:pem_entry_decode(hd(PemEntries)), Base64Sign = base64:decode(Sign), public_key:verify(DataBin, DigestType, Base64Sign, RSAPubKey).
产生RSA签名
-spec gen_rsa_sign(MsgBin, DigestType, KeyBin) -> binary() when MsgBin :: binary(), DigestType :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512', KeyBin :: binary(). gen_rsa_sign(MsgBin, DigestType, KeyBin) -> [Entry] = public_key:pem_decode(KeyBin), RSAPriKey = public_key:pem_entry_decode(Entry), SignBin = public_key:sign(MsgBin, DigestType, RSAPriKey), base64:encode(SignBin).
例子:
-module(rsa_test). -compile([export_all]). -define(RSA_PUBLIC_KEY, <<"-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAviTwX/3TPgo1YCDW4/Za aoerPaszmR7BxwdSC79JMAV/kniPBwqlB5EaIKSGw/bG0ciu8wcwEwZuADVO1sNo blo/O6r74i7i/90h/kJy8xI+BqGl0HccHOhC+yTA+wBXyYR8dkkqbNRJfwq0/cuf 5HIFi8r6dWMEEDytOiAcyUpZzgFj6cZ5JYJkkIqecm0QfnyZdY97l8s4zgIEFPC1 7fOP3h5QvjL76G9lADd37m1VhqUvCp0DZfbXxe8CtBQGJmVG11YkwrTQEQploDPZ p0GdOgfw/1gx7D5Y18ucfQHye6f/GM9+vkjuxIxf1YXxnxcwtFWEhjfviPHxWSZ8 kQIDAQAB -----END PUBLIC KEY-----">>). -define(RSA_PRIVATE_KEY, <<"-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAviTwX/3TPgo1YCDW4/ZaaoerPaszmR7BxwdSC79JMAV/kniP BwqlB5EaIKSGw/bG0ciu8wcwEwZuADVO1sNoblo/O6r74i7i/90h/kJy8xI+BqGl 0HccHOhC+yTA+wBXyYR8dkkqbNRJfwq0/cuf5HIFi8r6dWMEEDytOiAcyUpZzgFj 6cZ5JYJkkIqecm0QfnyZdY97l8s4zgIEFPC17fOP3h5QvjL76G9lADd37m1VhqUv Cp0DZfbXxe8CtBQGJmVG11YkwrTQEQploDPZp0GdOgfw/1gx7D5Y18ucfQHye6f/ GM9+vkjuxIxf1YXxnxcwtFWEhjfviPHxWSZ8kQIDAQABAoIBAD/SylSOMI/MgWoI 29ic4nCLpXEHvEQTTNvvmxySUpCp585UZT3p1scZb3mxgALbHJViFUdCDGL2b4nm WtY/tRgFduAiXnXnYw6bPUPJLihk4Sj8rVmyAV+6nnEKPzSBQvZDYDucB3+MKjdY crQV20+k7jOkKDmqyLxigYrXKJJvq9LzJk9ShXBtZq4voWGlttjYIKIL76cM1BiF +msjBI82PUVnDOMU2t7niN6ppwwZaBE3MLFbN52diO+ziYW3gT6k7yCNd9PH1XWH cLNwUjQZXM7uUTzih336+gFjwC/42gBq6zBHHkFmIfqfX0qLp0UMFXOBZLZu3gJ1 nv4hnVkCgYEA8MysfaYSIBt5pxQZwL+CTcuf84DUQKfdfsIbwAsFO+BaBsh17FR4 jk23/qQU46Ko4cPg4NSDnao4WIaL/89Gqf01sy1xAxCjqlpURT9KoZIksyV0mp12 Kw9W+a8Dbk9NqnOE2C0UjbJl2hDt37FS+DQYUkGjQMF7ofOjmM6M8kMCgYEAyiWs 9PIF/LJlAxUqsohPsqHuBHMnWGo7eYNMbm660AcYxf/AnjPxbVnkKPVk0qbz9Eb6 AGuh5J4908ps16JvBBBZeWRvnM4SEFrVzQVn3JWMb9ZlNGkN5T+Di8vTN7N/zAI2 /J3TZbGlXPwI5A+u2FwJkc8KhTgpD64TJBsnGpsCgYEAscOXLybzSIqf80zuehGm 40GIcl3P029ZH6OyksJP+dT1AP7pty7g1MThKPX+idHh9NEC6VdZVoJ8GDYzkgR1 uTY5d237ePTGrhMDFR/VO5PEzg+/lgjaXI11etvNn5ih0Ex5bJFTFAv4DtTilnm0 s5DZx5e3Ki3r1DIlur/44zsCgYBR8S/JIwp2QsJbm4rxT/wuhyF6wEsktfth6G1l HpGvnhDWwjOMbbXiA9xPFhpGodKmJNdWsEqx58tcPOQeDQQ/e3kpkiMERyxfYNLm BtjxO9Xvx9LCigtN8I8cbgUywRp+0i8D+94jjP1hUfEwsYLIxZZDes/i7L8IUiIE MtWJHQKBgQCCfvf+wGBJHpSX4ehHUgyvjjnaYE1UQzKspE+zFDZlqZDRiN3V2Qgu TM7rHyN61rECfACaDISWEPuGKntyVD98xNg9pdNl1pABVfP+msCPwvjNLYysKnwc GL+GEGGjvFEd6c0Ai+sobxs/cftbhzakZrBXvIjis/GTuKN/90uIVA== -----END RSA PRIVATE KEY-----">>). test() -> DataBin = make_data(), Sign = gen_rsa_sign(DataBin, 'sha', ?RSA_PRIVATE_KEY), check_rsa_sign(DataBin, Sign, ?RSA_PUBLIC_KEY, 'sha'). % -spec check_rsa_sign(DataBin, Sign, RSAPublicKeyBin, DigestType) -> boolean when % DataBin :: binary(), % Sign :: binary(), % RSAPublicKeyBin :: binary() % DigestType :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'. check_rsa_sign(DataBin, Sign, RSAPublicKeyBin, DigestType) -> PemEntries = public_key:pem_decode(RSAPublicKeyBin), RSAPubKey = public_key:pem_entry_decode(hd(PemEntries)), Base64Sign = base64:decode(Sign), public_key:verify(DataBin, DigestType, Base64Sign, RSAPubKey). % -spec gen_rsa_sign(MsgBin, DigestType, KeyBin) -> binary() when % MsgBin :: binary(), % DigestType :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512', % KeyBin :: binary(). gen_rsa_sign(MsgBin, DigestType, KeyBin) -> [Entry] = public_key:pem_decode(KeyBin), RSAPriKey = public_key:pem_entry_decode(Entry), SignBin = public_key:sign(MsgBin, DigestType, RSAPriKey), base64:encode(SignBin). make_data() -> <<"123456">>.
上面的公钥和私钥可以使用RSA的相关工具也可以使用在线的web工具生成。
注:可把上面的公钥和私钥放在文件中,然后读文件处理。可以把key放在文件中,如pub.key 和pri.key,具体如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
test() -> DataBin = make_data(), % Sign = gen_rsa_sign(DataBin, 'sha', ?RSA_PRIVATE_KEY), {ok, PriKey} = rsa_private_key(), Sign = gen_rsa_sign(DataBin,'sha', PriKey), % check_rsa_sign(DataBin, Sign, ?RSA_PUBLIC_KEY, 'sha'). {ok, PubKey} = rsa_public_key(), check_rsa_sign(DataBin, Sign, PubKey, 'sha'). % -spec check_rsa_sign(DataBin, Sign, RSAPublicKeyBin, DigestType) -> boolean when % DataBin :: binary(), % Sign :: binary(), % RSAPublicKeyBin :: binary() % DigestType :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'. check_rsa_sign(DataBin, Sign, RSAPublicKeyBin, DigestType) -> PemEntries = public_key:pem_decode(RSAPublicKeyBin), RSAPubKey = public_key:pem_entry_decode(hd(PemEntries)), Base64Sign = base64:decode(Sign), public_key:verify(DataBin, DigestType, Base64Sign, RSAPubKey). % -spec gen_rsa_sign(MsgBin, DigestType, KeyBin) -> binary() when % MsgBin :: binary(), % DigestType :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512', % KeyBin :: binary(). gen_rsa_sign(MsgBin, DigestType, KeyBin) -> [Entry] = public_key:pem_decode(KeyBin), RSAPriKey = public_key:pem_entry_decode(Entry), SignBin = public_key:sign(MsgBin, DigestType, RSAPriKey), base64:encode(SignBin). make_data() -> % <<"123456">>. list_to_binary(md5:test()). read_rsa_key(FileName) -> file:read_file(FileName). rsa_public_key() -> read_rsa_key("pub.key"). rsa_private_key() -> read_rsa_key("pri.key").
其实,注意2点即可:
1)公钥加密,私钥解密;
2)私钥负责签名,公钥负责验证。