本文介绍,使用命令行和编程语言(nodejs和java),将字符串用RSA加密和解密。
命令行:openssl
使用Mac,openssl自带了,以下使用步骤在Mac OSX 10.9.2下测试通过。
生成公钥和私钥
生成1024位的私钥:
openssl genrsa -out mykey.pem 1024
可以再通过命令将mykey.pem文件中的公钥提取出来:
openssl rsa -in mykey.pem -pubout > mykey.pub
使用公钥加密字符串
使用上面生成的公钥加密文件。生成一个文件:
echo "使用RSA加密解密字符串" > plain.txt
加密字符串并存入一个新的文件中:
cat plain.txt | openssl rsautl -encrypt -pubin -inkey mykey.pub >cipher.txt
使用私钥解密字符串
输入下面的命令可讲密文解密显示在终端上:
cat cipher.txt | openssl rsautl -decrypt -inkey mykey.pem
nodejs
nodejs的模块crypto并没有支持RSA,需要第三方的实现。
ursa,底层使用openssl,实习了RSA的功能。
我稍作改动:
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63var ursa = require("ursa");
var clearText='使用RSA加密解密字符串';
var keySizeBits = 1024;
var keyPair = ursa.generatePrivateKey(keySizeBits, 65537);
var encrypted = encrypt(clearText, keySizeBits/8);
console.log('加密后的数据:'+encrypted);
var decrypted = decrypt(encrypted, keySizeBits/8);
console.log('加密数据解密:'+decrypted);
function encrypt(clearText, keySizeBytes){
var buffer = new Buffer(clearText);
var maxBufferSize = keySizeBytes - 42; //according to ursa documentation
var bytesDecrypted = 0;
var encryptedBuffersList = [];
//loops through all data buffer encrypting piece by piece
while(bytesDecrypted < buffer.length){
//calculates next maximun length for temporary buffer and creates it
var amountToCopy = Math.min(maxBufferSize, buffer.length - bytesDecrypted);
var tempBuffer = new Buffer(amountToCopy);
//copies next chunk of data to the temporary buffer
buffer.copy(tempBuffer, 0, bytesDecrypted, bytesDecrypted + amountToCopy);
//encrypts and stores current chunk
var encryptedBuffer = keyPair.encrypt(tempBuffer);
encryptedBuffersList.push(encryptedBuffer);
bytesDecrypted += amountToCopy;
}
//concatenates all encrypted buffers and returns the corresponding String
return Buffer.concat(encryptedBuffersList).toString('base64');
}
function decrypt(encryptedString, keySizeBytes){
var encryptedBuffer = new Buffer(encryptedString, 'base64');
var decryptedBuffers = [];
//if the clear text was encrypted with a key of size N, the encrypted
//result is a string formed by the concatenation of strings of N bytes long,
//so we can find out how many substrings there are by diving the final result
//size per N
var totalBuffers = encryptedBuffer.length / keySizeBytes;
//decrypts each buffer and stores result buffer in an array
for(var i = 0 ; i < totalBuffers; i++){
//copies next buffer chunk to be decrypted in a temp buffer
var tempBuffer = new Buffer(keySizeBytes);
encryptedBuffer.copy(tempBuffer, 0, i*keySizeBytes, (i+1)*keySizeBytes);
//decrypts and stores current chunk
var decryptedBuffer = keyPair.decrypt(tempBuffer);
decryptedBuffers.push(decryptedBuffer);
}
//concatenates all decrypted buffers and returns the corresponding String
return Buffer.concat(decryptedBuffers).toString();
}
这个代码没有说清楚,如果key文件是已经生成好的,会是怎样。它的key是直接在代码中生成和使用的。
下面,参考ursa项目的test.js文件,写了个用私钥文件解析密文的代码。
1
2
3
4
5
6
7
8var ursa = require("ursa");
var fs = require("fs");
var privateKey=ursa.createPrivateKey(fs.readFileSync(__dirname + "/mykey.pem"));
var encryptData=fs.readFileSync(__dirname + "/cipher.txt");
var decryptedData=privateKey.decrypt(encryptData,undefined,'utf8',ursa.RSA_PKCS1_PADDING);
console.log('加密数据解密:'+decryptedData);
这里如果使用test.js默认的方式:
1var decryptedData=privateKey.decrypt(encryptData,undefined,'utf8');
即没有ursa.RSA_PKCS1_PADDING参数,会报类似下面的错:
Error: error:0407A079:rsa routines:RSA_padding_check_PKCS1_OAEP:oaep decoding errorThe mode ursa.RSA_PKCS1_PADDING is also supported.
java
RSA的java实现早就有了,但是因为是Android所以可能会特殊一些,比如有些包(非标准包)没有的情况。
看到这篇文章Android Encryption with the Android Cryptography API,Chunyen Liu写的,看姓名拼写应该是个华人。主要阅读Asymmetric Encryption Example - RSA这部分即可。
时间关系,就不再给出实现代码了。