引子
  目前做一款金融产品,由于涉及到资金安全,采用动态公钥的方式,即客户端每次登录服务端返回一个不同的XML串,由公钥的模数和指数构成,我需要用这个串生成公钥加密相关信息。
服务端返回的XML串形如:

<RSAKeyValue>
<Modulus>
wVwBKuePO3ZZbZ//gqaNuUNyaPHbS3e2v5iDHMFRfYHS/bFw+79GwNUiJ+wXgpA7SSBRhKdLhTuxMvCn1aZNlXaMXIOPG1AouUMMfr6kEpFf/V0wLv6NCHGvBUK0l7O+2fxn3bR1SkHM1jWvLPMzSMBZLCOBPRRZ5FjHAy8d378=
</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>

推荐看下这篇博客快速了解一下RSA:http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html

问题

  • 对RSA不了解。
  • 如何用所谓的模数和指数生成公钥来加密相关信息。

过程

  熟悉RSA。先看下openssl库中RSA结构体的定义。

struct rsa_st
{
/* The first parameter is used to pickup errors where
* this is passed instead of aEVP_PKEY, it is set to 0 */
int pad;
long version;
const RSA_METHOD *meth;
/* functional reference if 'meth' is ENGINE-provided */
ENGINE *engine;
BIGNUM *n;
BIGNUM *e;
BIGNUM *d;
BIGNUM *p;
BIGNUM *q;
BIGNUM *dmp1;
BIGNUM *dmq1;
BIGNUM *iqmp;
/* be careful using this if the RSA structure is shared */
CRYPTO_EX_DATA ex_data;
int references;
int flags; /* Used to cache montgomery values */
BN_MONT_CTX *_method_mod_n;
BN_MONT_CTX *_method_mod_p;
BN_MONT_CTX *_method_mod_q; /* all BIGNUM values are actually in the following data, if it is not
* NULL */
char *bignum_data;
BN_BLINDING *blinding;
BN_BLINDING *mt_blinding;
};

  开始推荐的博客中有关于RSA模数和指数的介绍,对应到结构中分别是其中的 n 和 e ,模反数对应d,最开始的质数因子对应 p和 q。n和e决定了公钥,n和d决定了私钥。结构体中其它元素不论,能知道的是模数和指数决定了公钥。

  如果能生成一个der或者pem文件,就可以用系统的方法去获取公钥,如下:

 // 1 der证书的base64编码形式
NSString *cert = @"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBXAEq5487dlltn/+Cpo25Q3Jo8dtLd7a/mIMcwVF9gdL9sXD7v0bA1SIn7BeCkDtJIFGEp0uFO7Ey8KfVpk2Vdoxcg48bUCi5Qwx+vqQSkV/9XTAu/o0Ica8FQrSXs77Z/GfdtHVKQczWNa8s8zNIwFksI4E9FFnkWMcDLx3fvwIDAQAB"; // 2 解码base64
NSData *publicKeyFileContent = [NSData dataFromBase64String:cert]; // 3 创建der证书对象
certificate = SecCertificateCreateWithData(kCFAllocatorDefault, ( __bridge CFDataRef)publicKeyFileContent);
if (certificate == nil) {
DLog(@"Can not read certificate from pub.der");
return nil;
}
// 4 验证证书
policy = SecPolicyCreateBasicX509();
OSStatus returnCode = SecTrustCreateWithCertificates(certificate, policy, &trust);
if (returnCode != ) {
DLog(@"SecTrustCreateWithCertificates fail. Error Code: %ld", returnCode);
return nil;
} // 5 返回公钥
SecTrustResultType trustResultType;
returnCode = SecTrustEvaluate(trust, &trustResultType);
if (returnCode != ) {
DLog(@"SecTrustEvaluate fail. Error Code: %ld", returnCode);
return nil;
} // 不管是否信任都会尝试返回公钥,也有可能被信任但是返不回公钥
publicKey = SecTrustCopyPublicKey(trust);
if (publicKey == nil) {
DLog(@"SecTrustCopyPublicKey fail");
return nil;
} maxPlainLen = SecKeyGetBlockSize(publicKey) - ;

  一番尝试后没有搞定,之后转向第三方库,比如openssl,openssl用C++实现。可以借助该库用模数和指数构造公钥。在网上也找到一篇解决这个问题的博客:Converting RSA public key Modulus and Exponent into PEM file

unsigned char *base64_decode(const char* base64data, int* len) {
BIO *b64, *bmem;
size_t length = strlen(base64data);
unsigned char *buffer = (unsigned char *)malloc(length);
b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
bmem = BIO_new_mem_buf((void*)base64data, length);
bmem = BIO_push(b64, bmem);
*len = BIO_read(bmem, buffer, length);
BIO_free_all(bmem);
return buffer;
} BIGNUM* bignum_base64_decode(const char* base64bignum) {
BIGNUM* bn = NULL;
int len;
unsigned char* data = base64_decode(base64bignum, &len);
if (len) {
bn = BN_bin2bn(data, len, NULL);
}
free(data);
return bn;
} EVP_PKEY* RSA_fromBase64(const char* modulus_b64, const char* exp_b64) {
BIGNUM *n = bignum_base64_decode(modulus_b64);
BIGNUM *e = bignum_base64_decode(exp_b64); if (!n) printf("Invalid encoding for modulus\n");
if (!e) printf("Invalid encoding for public exponent\n"); if (e && n) {
EVP_PKEY* pRsaKey = EVP_PKEY_new();
RSA* rsa = RSA_new();
rsa->e = e;
rsa->n = n;
EVP_PKEY_assign_RSA(pRsaKey, rsa);
return pRsaKey;
} else {
if (n) BN_free(n);
if (e) BN_free(e);
return NULL;
}
} void assert_syntax(int argc, char** argv) {
if (argc != ) {
fprintf(stderr, "Description: %s takes a RSA public key modulus and exponent in base64 encoding and produces a public key file in PEM format.\n", argv[]);
fprintf(stderr, "syntax: %s <modulus_base64> <exp_base64> <output_file>\n", argv[]);
exit();
}
}

  生成pem文件之后可以从pem文件里面读取公钥加密相关信息。

  最后封装了一下,放在github上:https://github.com/yrs244742688/GeneratePemWithMoAndEx

注解

  ASN.1:ASN.1抽象语法标记(Abstract Syntax Notation One) ASN.1是一种 ISO/ITU-T 标准,描述了一种对数据进行表示、编码、传输和解码的数据格式。它提供了一整套正规的格式用于描述对象的结构,而不管语言上如何执行及这些数据的具体指 代,也不用去管到底是什么样的应用程序。标准的ASN.1编码规则有基本编码规则(BER,Basic Encoding Rules)、规范编码规则(CER,Canonical Encoding Rules)、唯一编码规则(DER,Distinguished Encoding Rules)、压缩编码规则(PER,Packed Encoding Rules)和XML编码规则(XER,XML Encoding Rules)。

  x.509 : 常见通用的证书格式。

  der:DER是ASN.1编码规则的其中一种。x.509证书通过DER编码(ASCII)后缀是:.DER .CER .CRT,通过PAM编码(Base64)的后缀是:.PEM .CER .CRT。.cer/.crt是用于存放证书,它是2进制形式存放的,不含私钥。

  pem文件 : der文件经过base64转码后的文件。

(Email: yangxu0905@foxmail.com)

RSA加密:利用模数和指数生成公钥加密的更多相关文章

  1. 转发:已知rsa的模数和指数 生成pem公钥文件

    1.安装cryptographysudo pip3 install cryptography 2.代码 #coding:utf8# pupulate-pub-key-v3.py#from crypto ...

  2. RSA 加密

    iOS开发教程-iOS中的RSA加解密 在移动应用开发中常常遇到数据传输安全性的问题,尤其是在账户安全以及支付场景中的订单数据.或支付信息的传输中,正规的公司一定会要求对数据进行加密,当然有创业初期的 ...

  3. python RSA加密解密及模拟登录cnblog

    1.公开密钥加密 又称非对称加密,需要一对密钥,一个是私人密钥,另一个则是公开密钥.公钥加密的只能私钥解密,用于加密客户上传数据.私钥加密的数据,公钥可以解密,主要用于数字签名.详细介绍可参见维基百科 ...

  4. 利用openssl进行RSA加密解密

    openssl是一个功能强大的工具包,它集成了众多密码算法及实用工具.我们即可以利用它提供的命令台工具生成密钥.证书来加密解密文件,也可以在利用其提供的API接口在代码中对传输信息进行加密. RSA是 ...

  5. RSA加密、解密、公钥私钥生成

    有时项目中需要用到一些加密和解密工具,这里之前整理了一个demo,记录一下,方便查询 package com.test; import java.security.KeyFactory; import ...

  6. RSA加密通信小结(三)--生成加解密所需的SSL命令与流程

    在iOS中使用RSA加密解密,需要用到.der和.p12后缀格式的文件,其中.der格式的文件存放的是公钥(Public key)用于加密,.p12格式的文件存放的是私钥(Private key)用于 ...

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

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

  8. 【转】iOS安全之RSA加密/生成公钥、秘钥 pem文件

    在iOS中使用RSA加密解密,需要用到.der和.p12后缀格式的文件,其中.der格式的文件存放的是公钥(Public key)用于加密,.p12格式的文件存放的是私钥(Private key)用于 ...

  9. RSA加密原理与秘钥、公钥生成

    RSA加密(非对称加密) RSA公开密钥密码体制.所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制.(不可逆向运算的加密方法) ...

随机推荐

  1. Codeforces 375D Tree and Queries(DFS序+莫队+树状数组)

    题目链接  Tree and Queries 题目大意  给出一棵树和每个节点的颜色.每次询问$vj, kj$ 你需要回答在以$vj$为根的子树中满足条件的的颜色数目, 条件:具有该颜色的节点数量至少 ...

  2. Codeforces 246E Blood Cousins Return(树上启发式合并)

    题目链接 Blood Cousins Return #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) f ...

  3. eclipse启动的时候 一直未响应状态 然后闪退

    解决方案:在你的工作目录中,有一个.metadata目录,里面是工作区及各插件的信息,删除此目录可以解决问题.保险起见,先剪切到另一地方.再重启启动.

  4. JDK1.8和Spring 3.2.0 的坑

    上午 org.apache.catalina.core.StandardContext listenerStart严重: Exception sending context initialized e ...

  5. js/jq仿window文件夹框选操作插件

    0.先给大家看看效果: 1.创建一个index.html文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ...

  6. javascript --- 兼容的那些事

    绑定事件 var addEvent = function( obj, type, fn ) { if (obj.addEventListener) obj.addEventListener( type ...

  7. Pixhawk之姿态解算篇(1)_入门篇(DCM Nomalize)

    一.开篇 慢慢的.慢慢的.慢慢的就快要到飞控的主要部分了,飞控飞控就是所谓的飞行控制呗,一个是姿态解算一个是姿态控制,解算是解算,控制是控制,各自负责各自的任务.我也不懂.还在学习中~~~~ 近期看姿 ...

  8. excel怎么把文本格式的数字转换为数字,且把前面的撇号去掉

    excel把文本格式的数字转换为数字,且把前面的撇号去掉方法:1.选中要处理的列,在“数据”菜单下,选择“分列”.2.在“分列”向导对话框里,选择“分隔符号”,并点击下一步.3.在“分列”向导对话框第 ...

  9. cache数据库之表的存储结构

    1.我们已经建了一个person类,接下来就是表的存储结构 2.打开Inspector,先输入rowid名字为p_RowID,选class->Storage 3.新建一个Storage,选择Ca ...

  10. vdWebControl.js去水印

    vdWebControl.js可以在浏览器中展示cad图形(须要使用其自家的转换工具把cad转换为vds格式.工具免费,但转换完成后的文件带水印信息),支持编辑图形. vdWebControl.js试 ...