Erlang 使用rsa不对称密钥进行签名和验签

发布时间 2023-10-17 20:54:45作者: J6`

背景:合作方要求使用rsa(sha256)不对称密钥进行签名和验签 erlang版本:OTP20.3

  1. 使用工具生成rsa密钥对(自行百度)获得一个公钥和私钥
    公钥内容如:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApiwI+2ZT0eWUiLQ1p6JV
Kv70ae...
-----END PUBLIC KEY-----

私钥内容如:

-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEApiwI+2ZT0eWUiLQ1p6JVKv70aeVATwLryqIUDjvBnPuz3Zme
XofqVjV0G35mexMmzWU1tYOWFBq0YKGimHNMcllHsw/+RrM/gMr+M2GfNWKxVJ+Q
2kfH+oRATe+HqO5x68zYlmEbkpTrrM4lriK8lOMpvetDT2RsCpKguckMADa4eTEV
/9RxSOhVghN/7XXQDOWzp9oVgkMvDN5tDkjcCidphrwc/AKZjn3httsxpU0SSZZp
0EykKv9wEhG7f66yDplU8hhg9p3iw6UceptQSV8xBn5YfY1Vsni+8z92e9sKqqq/
Ir6TxcXvWREqdii94F2TxFFRLC4t9kSx9iBxBwIDAQABAoIBADsz0xtmUJSme63c
roUD494GqaOUxr2fp8wwxH5xscAxONrJoU/Ckq2WK8Cj3vUYVKm21lTOBckx3nPT
Am/YHDNdNZtJJmmf8Q78w2Yg8Kz/dXhVxTDPhCLvvU1G+okoMrQ07jFddYpavkB5
zZjlzVQqPrPoPrnpaEi4BsVKKJlmT8kuLm4vdrzERm0kEskxzKzIfVm0tfdiLbYo
C48dfk1ve7DYr8CeWl5jnek5QIl...
-----END RSA PRIVATE KEY-----
  1. 公钥提供给合作方,并向合作方要其公钥
  2. 实现签名sign和验签verify方法
    3.1 将密钥转化成erlang能用的格式
    % 将私钥字符串(二进制)转化成erlang的#'RSAPrivateKey'{}结构体
    % 字符串可以写死在erl文件中,或者存在外部文件,通过erlang的读文件内容接口获取
    private_key() ->
      PemBin = <<"-----BEGIN RSA PRIVATE KEY-----...">>,
      [RSAPrivateKey] = public_key:pem_decode(PemBin),
      PrivateKey = public_key:pem_entry_decode(RSAPrivateKey),
      PrivateKey.
    
    % 将合作方的公钥转化成erlang的#'RSAPublicKey'{}结构体,过程同上
    public_key() ->
        PemBin = <<"-----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApiwI+2ZT0eWUiLQ1p6JV
    ...
    -----END PUBLIC KEY-----">>,
        [RSAPublicKey] = public_key:pem_decode(PemBin),
        PublicKey = public_key:pem_entry_decode(RSAPublicKey),
        PublicKey.
    
    3.2 签名sign
    % Payload是binary() (我的业务还要注意是utf8编码)
    -spec sign(Payload::binary(), Key::public_key:rsa_private_key()) -> binary().
    sign(Payload, Key) ->
        Signature = public_key:sign(Payload, 'sha256', Key),
        base64:encode(Signature).
    
    3.3 验签verify
    -spec verify(Payload::binary(), Signature::binary()|iolist(), Key::public_key:rsa_public_key()) -> boolean().
    verify(Payload, Signature, Key) ->
        Signature1 = base64:decode(Signature),
        public_key:verify(type:unicode_binary(Payload), 'sha256', Signature1, Key).
    
  3. 例子
Payload = <<"abc">>,
Signature = sign(Payload, private_key())
% 自我验证的话使用自己的公钥而不是合作商提供的public_key()
true = verify(Payload, Signature, public_key())