Elixir使用RSA公钥加密Base64密码报MatchError错误
问题根因
匹配错误由两个明确的代码问题导致:
:public_key.pem_decode()返回的PEM条目是三元组结构:{密钥类型原子, DER编码二进制串, 密钥加密状态标记},你写的二元组匹配{:RSAPublicKey, public_key3}和实际返回的{:RSAPublicKey, <<48, 129, ...>>, :not_encrypted}结构不匹配,报错信息里已经完整打印了右值的实际结构。- 即使元组拆分正确,拿到的DER二进制是编码后的内容,不是加密函数可直接识别的公钥结构,必须先做解码转换。
可直接运行的实现方案
方案1:兼容ExPublicKey库的写法
不需要手动拆分元组,直接用内置函数把PEM条目解码成标准公钥结构即可:
base64_password = Base.encode64(enc_password) # 读取并解析PEM公钥文件 pem_entries = "/Users/owen/loomis/io_backend/priv/certs/in2publickey.pem" |> File.read!() |> :public_key.pem_decode() # 解码为ExPublicKey可识别的原生RSA公钥结构 rsa_public_key = pem_entries |> Enum.at(0) |> :public_key.pem_entry_decode() # 执行公钥加密,注意填充方式必须和对端解密配置完全一致,常用选项为:rsa_pkcs1_padding、:rsa_pkcs1_oaep_padding {:ok, cipher_text} = ExPublicKey.encrypt_public(base64_password, rsa_public_key, rsa_padding: :rsa_pkcs1_padding)
方案2:无第三方依赖的原生实现
完全可以不用引入ExPublicKey库,直接用Erlang自带的:public_key模块完成加密,兼容性更稳定:
base64_password = Base.encode64(enc_password) rsa_public_key = "/Users/owen/loomis/io_backend/priv/certs/in2publickey.pem" |> File.read!() |> :public_key.pem_decode() |> Enum.at(0) |> :public_key.pem_entry_decode() # 原生加密返回二进制密文,可根据业务需要转base64传输 cipher_text_raw = :public_key.encrypt_public(base64_password, rsa_public_key, rsa_padding: :rsa_pkcs1_padding) cipher_text = Base.encode64(cipher_text_raw)
避坑提示
- 你的代码里定义了读
.key后缀文件的rsa_public_key_path变量,后续实际读取的是.pem后缀的文件,注意核对路径,避免读错密钥。 - RSA加密对明文长度有限制,1024位密钥在PKCS1填充规则下最长只能加密117字节内容,如果待加密内容过长,建议先用AES对称加密明文,再用RSA加密AES密钥,避免触发明文长度超限错误。
- 两端的填充规则必须完全一致,否则会出现解密失败的问题。
内容的提问来源于stack exchange,提问作者Owen Hartnett
相关产品推荐
相关产品推荐

