zoukankan      html  css  js  c++  java
  • erlang的RSA签名与验签

      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,具体如下:

    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").
    View Code

    其实,注意2点即可:

    1)公钥加密,私钥解密;

    2)私钥负责签名,公钥负责验证。

  • 相关阅读:
    [LeetCode] Trips and Users 旅行和用户
    [LeetCode] Rising Temperature 上升温度
    [LeetCode] Delete Duplicate Emails 删除重复邮箱
    [LeetCode] Department Top Three Salaries 系里前三高薪水
    Spring boot Jackson基本演绎法&devtools热部署
    使用spring tool suite(STS)工具创建spring boot项目和出现错误后的处理
    Spring Boot 2.0官方文档之 Actuator
    springboot 使用webflux响应式开发教程(二)
    SpringBoot在自定义类中调用service层等Spring其他层
    springBoot单元测试-模拟MVC测试
  • 原文地址:https://www.cnblogs.com/unqiang/p/7010878.html
Copyright © 2011-2022 走看看