在js上做rsa,感觉jsencrypt这个是封装的比较好的,但用起来还是遇到了些坑,所以踩进代码里填填坑~

项目在这里 https://github.com/travist/jsencrypt

【rsa算法】

首先科普一下rsa:公钥私钥成对,用其中一个加密只能用另一个解密,常用公钥加密私钥解密。

一开始看到斯坦佛那个库,原始的算法实现:

长度,建议至少1024。模数n(常取默认65537)两边都要用。

指数e,和n一起就是公钥。指数d,和n一起就是私钥。质数p和q用于生成密钥对,然后就丢弃不公开。

具体算法网上一大把,就不多说了。

【ssl/ssh密钥对】

用服务器上的工具生成的密钥对,格式一般是如下,有开始行结束行,内容用base64转码。这里涉及一些国际编码规范,代码分析时在逐一解释。

-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAIA4OVgB4FRq4l5zjEmd4r/jswRcHlZQ
kg10p9rzG3VyXCPpa/ZkwOYy+kGq7a7BjAKTpic2cUNRim4m8HKTdc8CAwEAAQ==
-----END PUBLIC KEY-----

【代码分析】

加载公钥:setPublicKey->setKey->JSEncryptRSAKey->parseKey

RSAKey.prototype.parseKey = function (pem) {...}

注释写得非常好!

/**
...省略...
 *This method accepts public key
* in the rsaencryption pkcs #1 format (oid: 1.2.840.113549.1.1.1).
* The format is defined as:
* PublicKeyInfo ::= SEQUENCE {
* algorithm AlgorithmIdentifier,
* PublicKey BIT STRING
* }
* Where AlgorithmIdentifier is:
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER, the OID of the enc algorithm
* parameters ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1)
* }
* and PublicKey is a SEQUENCE encapsulated in a BIT STRING
* RSAPublicKey ::= SEQUENCE {
* modulus INTEGER, -- n
* publicExponent INTEGER -- e
* }
*/

代码如下:

 RSAKey.prototype.parseKey = function (pem) {
try {
...
var der = reHex.test(pem) ? Hex.decode(pem) : Base64.unarmor(pem);
var asn1 = ASN1.decode(der);
...
if (asn1.sub.length === 9) {
// Parse the private key.
}
else if (asn1.sub.length === 2) {
// Parse the public key.
var bit_string = asn1.sub[1];
var sequence = bit_string.sub[0];
modulus = sequence.sub[0].getHexStringValue();
this.n = parseBigInt(modulus, 16);
public_exponent = sequence.sub[1].getHexStringValue();
this.e = parseInt(public_exponent, 16);
}
else {
return false;
}
return true;
}
catch (ex) {
return false;
}
};

这里需要了解一下各种编码格式。hex和base64就不解释了。

ASN.1抽象语法标记,我的理解就是对数据进行结构化解析的规范:一个标准的ASN.1编码对象有四个域:对象标识域、数据长度域、数据域以及结束标志(可选,在长度不可知情况下需要,openssl中没有该标志)。

DER则是具体的编码实现。 http://baike.baidu.com/view/100318.htm#4

PKCS#1则是RSA中最基础的算法定义和密钥规定,讲人话就是定义了:公钥是元组(n,e),算法是n=q*p等一系列公式。https://en.wikipedia.org/wiki/PKCS1

这段代码两处亮点,一个是else if (asn1.sub.length === 2)判断公钥(没深究,反正靠子节点数判断);
两一个是var bit_string = asn1.sub[1];即前面有一段asn1.sub[0]是算法标识。

这里本身没有坑,但是生成公钥时如果命令不对应是会踩坑的(有一种命令是生成无算法标记的公钥)~~~

加密:encrypt->RSAEncrypt->pkcs1pad2 | doPublic->RSADoPublic

pkcs1pad2是做补位处理:

入参 var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3); 是(模位数+7)/8得到模的字节长度?

然后是一系列的移位操作,此处的作用是填入随机位使得每次加密的密文都不一样。http://blog.chinaunix.net/uid-21880738-id-1813144.html

RSADoPublic最终执行加密算法x^e (mod n)

至此,主要的算法、规范和坑基本上覆盖了,私钥和解密坑比较少,就不多说了。

最后,附送一个千年大坑,跨语言跨类库的时候不小心可能会遇到的 http://blog.chinaunix.net/uid-23069658-id-4282969.html

于这个js类库而言,-pubout出来的是可用的,而-RSAPublicKey_out出来的是不可用的。

与此对应,服务器openssl的类库中PEM_read_RSA_PUBKEY()读入是对应的,而PEM_read_RSAPublicKEY()读入是不对应的。

jsencrypt代码分析——openssl的rsa加密解密在js的实现的更多相关文章

  1. OpenSSL 中 RSA 加密解密实现源代码分析

    1.RSA 公钥和私钥的组成.以及加密和解密的公式: 2.模指数运算: 先做指数运算,再做模运算.如 5^3 mod 7 = 125 mod 7 = 6 3.RSA加密算法流程: 选择一对不同的.而且 ...

  2. openssl evp RSA 加密解密

    openssl evp RSA 加密解密 可以直接使用RSA.h 提供的接口 如下测试使用EVP提供的RSA接口 1. EVP提供的RSA 加密解密 主要接口: int EVP_PKEY_encryp ...

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

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

  4. 用openssl库RSA加密解密

    #include <stdio.h> #include <openssl/rsa.h> #include <openssl/pem.h> #include < ...

  5. jsencrypt代码分析

    jsencrypt代码分析——openssl的rsa加密解密在js的实现   在js上做rsa,感觉jsencrypt这个是封装的比较好的,但用起来还是遇到了些坑,所以踩进代码里填填坑- 项目在这里  ...

  6. 兼容javascript和C#的RSA加密解密算法,对web提交的数据进行加密传输

    Web应用中往往涉及到敏感的数据,由于HTTP协议以明文的形式与服务器进行交互,因此可以通过截获请求的数据包进行分析来盗取有用的信息.虽然https可以对传输的数据进行加密,但是必须要申请证书(一般都 ...

  7. C# Java间进行RSA加密解密交互(三)

    原文:C# Java间进行RSA加密解密交互(三) 接着前面一篇C# Java间进行RSA加密解密交互(二)说吧,在上篇中为了实现 /** * RSA加密 * @param text--待加密的明文 ...

  8. 基于OpenSSL的RSA加密应用(非算法)

    基于OpenSSL的RSA加密应用(非算法) iOS开发中的小伙伴应该是经常用der和p12进行加密解密,而且在通常加密不止一种加密算法,还可以加点儿盐吧~本文章主要阐述的是在iOS中基于openSL ...

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

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

随机推荐

  1. python-继承,父类,子类

    class Spell(object): def __init__(self, incantation, name): self.name = name self.incantation = inca ...

  2. hdu3966 Aragorn's Story 树链剖分

    题目传送门 题目大意: 有n个兵营形成一棵树,给出q次操作,每一次操作可以使两个兵营之间的所有兵营的人数增加或者减少同一个数目,每次查询输出某一个兵营的人数. 思路: 树链剖分模板题,讲一下树链剖分过 ...

  3. Gson反序列化泛型实例

    1 package com.ppmoney.g2.mapper; import com.google.common.reflect.TypeToken; import com.google.gson. ...

  4. 小a的计算器

    链接:https://ac.nowcoder.com/acm/contest/317/A来源:牛客网 小a的数学基础实在太差了,以至于他只会用计算器算数.他的计算器比较特殊,只有+,−,×,/+,−, ...

  5. vue指令与事件修饰符

    一.条件渲染指令 vue中提供了两个指令可以用于判断是否要显示元素,分别是v-if和v-show. 实例: <!DOCTYPE html> <html lang="en&q ...

  6. python 函数基础知识整理

    一.函数的定义: 定义:def 关键词开头,空格之后接函数名称和圆括号(),最后还有一个":". def 是固定的,不能变,必须是连续的def三个字母,不能分开... 空格 为了将 ...

  7. poj3187

    一.题意:给定n,求1~n的一个排列,这个排列需要满足以下两个要求:1.杨辉三角最后的和为sum  2.字典序最小 二.思路:暴力枚举每一个排列,然后计算和并与sum进行比较.这里我比较费解的是为什么 ...

  8. C#接收emoji表情存到sqlserver数据库

    1.将就的方法已找到,在保存前,Emoji表情字符串进行utf-8编码,然后写入数据表的nvarchar(max)字段,取出时再进行解码即可. c#的写法如下: 写入数据表前编码: string sH ...

  9. PIE SDK主/次要分析

    1.算法功能简介 主要分析功能是采用类似卷积滤波的方法将较大类别中的虚假像元归到该类中,首先定义一个变换核尺寸,然后用变换核中占主要地位(像元最多)类别数代替中心像元的类别数,次要分析相反,用变换核中 ...

  10. Flutter编程:Flutter命令行的学习

    1.创建 Flutter 工程 flutter create <output directory> D:\notebook\flutter\projects\ui_tutorial\lay ...