1.对方要求我们的私钥是pkcs8格式,但是实际的公钥没有用pkcs8转换之后的私钥完成,所以是可以不是pkcs8的格式的。我们加签跟格式没有关系。
2.数据格式很重要,to_mpint而非crypto:mpint生成mpint的高精度整型,to_mpint有是自己写的函数,但实际上有很多开源代码里面有,所以要多看开源代码及想到直接调用。
3.RSA加密加签原理:
(1).加密,可以用私钥加密,公钥解密。
(2).加密,也可以用公钥加密,私钥解密。
(3).加签,必须要用私钥加签,公钥验证。
(4).调用的方法不同。原理如下:
RSA数据的hash^私钥 mod M = 签名
签名 ^公钥 mod M = 数据的hash
数据 ^公钥 mod M = 密文
密文 ^私钥 mod M = 数据
4.调用erlang的crypto模块加密
5.生成密钥的方法是一样的。
(1).按装openssl(基础环境中有此软件,无需安装)
(2).输入openssl
生成私钥: genrsa -out private_key.pem 1024
(3).转换成pkcs8格式(可无)pkcs8 -topk8 -inform PEM -in private_key.pem -outform PEM -nocrypt -out rsa_private_key.pem
(4).用私钥生成公钥: rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
6.对于加签,是使用crypto:rsa_sign还是crypto:sign,但是实际上sign是新版本的,我方安装版本跟不上。
7.对于未做过的操作,应该有几步:
(1)确认要使用的方法
(2)对于该方法所要的参数,如果格式不符合,要找到对应的转换方式(可以看开源库)
但是方向要弄对,要先找到解决方法,再找原因。
====================================加密================================================
加密(用私钥加密,公钥解密)
-module(crypto_api).
-include_lib("public_key/include/public_key.hrl").
-include("ewp.hrl").
-include("backend.hrl").
-export([testencode/1,%%测试加密函数
testdecode/1 %%测试解密函数
]).
%%Params为原始内容,数据类型为binary,_Foo为加密后的密文
case Type of
RSA ->
crypttest:testencode(Mobile); crypto_api:testencode()
_ ->
sm:
testencode(Params) ->
{ok, PemBinary} = file:read_file("./public/security/rsa_private_key.pem"),%%读取私钥中的pem二进制码
[Entry] = public_key:pem_decode(PemBinary),%%读取私钥中的pem二进制码,生产一个实体
RSAPrivateKey = public_key:pem_entry_decode(Entry),%%实体生产私钥Key
%%调用erlang的crypto模块加密
PrivKey = [crypto:mpint(RSAPrivateKey#'RSAPrivateKey'.publicExponent), crypto:mpint(RSAPrivateKey#'RSAPrivateKey'.modulus), crypto:mpint(RSAPrivateKey#'RSAPrivateKey'.privateExponent)] ,
_Foo = crypto:rsa_private_encrypt(Params,PrivKey,rsa_pkcs1_padding).

testdecode(Params) ->
{ok, PemBinary} = file:read_file("./public/security/rsa_public_key.pem"),
[Entry] = public_key:pem_decode(PemBinary),
RSAPublicKey = public_key:pem_entry_decode(Entry),
PubKey = [crypto:mpint(RSAPublicKey#'RSAPublicKey'.publicExponent), crypto:mpint(RSAPublicKey#'RSAPublicKey'.modulus)],
_Bar = crypto:rsa_public_decrypt(Params,PubKey,rsa_pkcs1_padding).

============================加签,MD5摘要生成=======================================================
-module(....).

-include("ewp.hrl").
-include("backend.hrl").
-include_lib("public_key/include/public_key.hrl").
-define(URL,"https://jiaofei........html").

-export([
'SN0001'/3, % 第三方配置化
proplist_to_andlist/1
]).

'SN0001'(UserObj, TranID, P) ->
MOBILE_NO = user_obj:get_field('MOBILE_NO', UserObj), %% 手机号
USER_CODE = user_obj:get_field('USER_CODE', UserObj), %% 手机银行客户号
Url = ?URL,
RequestTime = "20170214142901", %%ewp_time:datetime_str()
Version = "2.0", %
App_id = "yfbm70058192e2017021301", %
Merchant_user_no = "43243", %%商户id之后给 USER_CODE
Terminal_type = "03",
Sign_type = "RSA",
Signkey_index = "0001", %%公钥索引 测试
SignMD = list_to_possign([{"request_time",RequestTime},{"version",Version},{"app_id",App_id}, {"merchant_user_no",Merchant_user_no},{"terminal_type",Terminal_type}]), %%数字签名
{ok, Privatekey} = file:read_file("./config/key/private_key.pem"),%%读取私钥中的pem二进制码
SignRSA = rsa_encode(SignMD,Privatekey),
Sign = yaws_api:url_encode(SignRSA),
PostDetail = Sign, %%实际要post给苏宁的参数
[{url,Url},{post,PostDetail}].

rsa_encode(Data,Priv_key) ->
[Entry] = public_key:pem_decode(Priv_key), %%读取私钥中的pem二进制码,生产一个实体
RSAPrivateKey = public_key:pem_entry_decode(Entry), %%实体生产私钥Key 私钥加密 加密的时候传参数为二进制的
PrivKey = [crypto:mpint(RSAPrivateKey#'RSAPrivateKey'.publicExponent),
crypto:mpint(RSAPrivateKey#'RSAPrivateKey'.modulus), crypto:mpint(RSAPrivateKey#'RSAPrivateKey'.privateExponent)],
Result = crypto:rsa_sign('sha',to_mpint(Data),PrivKey), %% crypto:rsa_sign('sha',NumberMpint,PrivKey) crypto:sign(rsa,md5,Number,PrivKey)
ResultBase = base64:encode(Result),
binary_to_list(ResultBase). %% 传回后台使用 变回字符串的类型

to_mpint(String) when is_list(String) ->
to_mpint(list_to_binary(String));
to_mpint(Bin) ->
Size = size(Bin),
<<Size:32/integer, Bin:Size/binary>>.

%% params: Proplist为[{...},.tuple..,{...}]格式。
%% 返回结果:key=value&key1=value1....
proplist_to_andlist(Proplist)->
Str1 = lists:foldl(
fun(X,Acc)->
{Key1,Value1} = X,
Key = atom_to_string(Key1),
Value = atom_to_string(Value1),
case [Key,Value] of
[_,""] ->
Acc; %%如果值为空,不放入该序列
[_," "] ->
Acc;
_ ->
case Acc of
[] ->
Acc ++ Key ++ "=" ++ Value;
" " ->
Acc ++ Key ++ "=" ++ Value;
_ ->
Acc ++ "&" ++ Key ++ "=" ++ Value
end
end
end,"",Proplist),
Str1.

%% params: Proplist为[{...},.tuple..,{...}]格式。
%% 返回结果:数字签名---MD5加密后的大写的16进制(按照微信规则商户支付密钥放置在串最后加密)
list_to_possign(Proplist)->
SortList = lists:keysort(1,Proplist), %%ASC码从小到大排序
Str1 = proplist_to_andlist(SortList), %%拼接成 Key1=value1&Key2=value2 无key商户支付密钥的序列
Res1 = Str1,
MD1 = erlang:md5(Res1), %%
<<Int:128>> = MD1, %% MD2 = backend_util:to_hexstr(MD1)
Str = integer_to_list(Int,16), %%生成大写的16进制
Str.

%% 如果参数A为atom则转换为string,如果本来就是string则还是string
atom_to_string(A)->
case is_atom(A) of
true ->
atom_to_list(A);
false ->
A
end.

RSA加密及加签的更多相关文章

  1. 微信小程序(17)-- RSA加密 解密 加签 验签

    RSA加密 解密 加签 验签 /** * 注:区分RSA私钥的类型,有pkcs1和pkcs8.pkcs8格式的私钥主要用于Java中 pkcs1格式: -----BEGIN RSA PRIVATE K ...

  2. C# 数字证书 RSA加密解密 加签验签

    KeyValuePair<string, string> keyPair = Encrypter.CreateRSAKey(); string privateKey = keyPair.V ...

  3. 【绝迹篇】RSA加密算法(私钥加签公钥验签)

    对于上上篇博客中我讲的一个故事,本文引用: https://www.cnblogs.com/ButterflyEffect/p/9851403.html 故事中提到的关于加密会出现,私钥加密,公钥解密 ...

  4. C++ 使用openssl库实现 DES 加密——CBC模式 && RSA加密——公加私解——私加公解

    之前工作上需要用C++把软件生成的用户序列号用des加密cbc的模式,加密后为二进制,转化为十六进制,然后提供给java写的授权码管理平台. java平台会根据用户序列号,生成一个授权码,授权码是用r ...

  5. Java RSA加密以及验签

    签名加密以及验签工具类: 一般秘钥分为3个key 1.自己生成的私钥, 2.通过私钥生成的公钥1 3.通过提交公钥1给某宝,获取的公钥2. RSA公钥加密算法简介 非对称加密算法.只有短的RSA钥匙才 ...

  6. rsa 加密 pkcs#1格式秘钥的格式化

    C++调用openssl库生成的秘钥对,通过传输传出来的只有秘钥的内容,没有秘钥的格式.而我们在调用openssl库加密解密时,传入的秘钥是需要包含格式的.C++调用openssl库需要的格式为pkc ...

  7. C++调用openssl库生成RSA加密秘钥对

    直接上代码.默认生成的是pkcs#1格式 // ---- rsa非对称加解密 ---- // #define KEY_LENGTH 1024 // 密钥长度 #define PUB_KEY_FILE ...

  8. ruby的加密方法整理(des rsa加密 加签)

    # coding:utf-8require 'openssl'require 'base64'#des加密并且base64编码def des_encrypt des_key, des_text des ...

  9. RSA加密解密及RSA加签验签

    RSA安全性应用场景说明 在刚接触RSA的时候,会混淆RSA加密解密和RSA加签验签的概念.简单来说加密解密是公钥加密私钥解密,持有公钥(多人持有)可以对数据加密,但是只有持有私钥(一人持有)才可以解 ...

随机推荐

  1. 安装archlinux的linux命令记录

    磁盘的分区:cfdisk 格式化分区:mkfs.ext4,mkswap,swapon 查看所有分区:lsblk /dev/sda 先挂载 / 分区:mount /dev/sda1 /mnt archl ...

  2. web前端学习历程--跨域问题

    一.同源策略 一个页面的ajax只能获取这个页面相同源(协议.域名.端口号都必须相同)的数据. 二.jsonp方法 1.json和jsonp JSON(JavaScript Object Notati ...

  3. Python之__slots__ &运算符重载反向运算

    1.运算符重载之反向运算 class A: def __init__(self,x): self.x = x def __add__(self, other): try: x = other.x re ...

  4. pageresponse.min.js自动缩放页面改写

    /* * 名称 :移动端响应式框架 * 作者 :白树 http://peunzhang.cnblogs.com * 版本 :v2.1 * 日期 :2015.10.13 * 兼容 :ios 5+.and ...

  5. TheFatRat一般使用

    利用它生成后门 第一种通常情况下速度很快,较稳定,但免杀效果极差 推荐使用第二种 免杀效果好,如下图 第一种是最新的模块,较免杀效果极好.还可伪造图标 第二种是旧的

  6. CSRF(Cross Site Request Forgery, 跨站域请求伪造)

    CSRF(Cross Site Request Forgery, 跨站域请求伪造) CSRF 背景与介绍 CSRF(Cross Site Request Forgery, 跨站域请求伪造)是一种网络的 ...

  7. 调用WebService的简单方法

    package com.xxx.webservice.internal.test; import java.net.MalformedURLException; import java.net.URL ...

  8. Python Redis 常用操作

    delete(*names) # 根据删除redis中的任意数据类型 exists(name) # 检测redis的name是否存在 keys(pattern='*') # 根据模型获取redis的n ...

  9. StringUtils工具类常用方法汇总(判空、转换、移除、替换、反转)

    Apache commons lang3包下的StringUtils工具类中封装了一些字符串操作的方法,非常实用,使用起来也非常方便.最近自己也经常在项目中使用到了里面的一些方法,在这里将常用的方法总 ...

  10. Servlet运行原理以及生命周期

    一.Servlet生命周期: Servlet加载.实例化.初始化.服务.销毁. 1.初始化init(): 当服务启动时,Servlet被装入tomcat或者其他服务器容器时执行(服务器容器从启动到停止 ...