我正在使用JSBN通过公钥/私钥对数据进行加密/解密。它适用于文本数据,包括十六进制字符串。
我的问题是现在我有了二进制数据,特别是Crypto-JS字数组,我需要用公钥加密并发送到另一个平台。
因此请考虑以下内容:
var key = CryptoJS.lib.WordArray.random(256/8);
var rsa = new RSAKey();
rsa.setPublic(modulus, exponent);
var encrypted_key = rsa.encrypt(key.toString());这是可行的,但这意味着'encrypted_key‘实际上是一个经过加密的十六进制字符串,而不是实际的密钥。我需要加密实际的密钥。
所以我在这里看到了两个挑战:
1)我不是百分之百确定如何从CryptoJS.lib.WordArray中获取实际字节--尽管这看起来并不是完全无法克服的。
2)我甚至不知道是否可以使用JSBN加密二进制数据。我想要一些指点来弄清楚怎么做。
有什么想法吗?
发布于 2013-05-23 11:51:58
JSBN库包含一个名为pkcs1pad2()的函数,它使用JavaScript的charCodeAt()函数将文本转换为数值。您将在第一个while()循环中看到转换代码:
function pkcs1pad2(s,n) {
if(n < s.length + 11) { // TODO: fix for utf-8
alert("Message too long for RSA");
return null;
}
var ba = new Array();
var i = s.length - 1;
while(i >= 0 && n > 0) {
var c = s.charCodeAt(i--);
if(c < 128) { // encode using utf-8
ba[--n] = c;
}
else if((c > 127) && (c < 2048)) {
ba[--n] = (c & 63) | 128;
ba[--n] = (c >> 6) | 192;
}
else {
ba[--n] = (c & 63) | 128;
ba[--n] = ((c >> 6) & 63) | 128;
ba[--n] = (c >> 12) | 224;
}
}
ba[--n] = 0;
var rng = new SecureRandom();
var x = new Array();
while(n > 2) { // random non-zero pad
x[0] = 0;
while(x[0] == 0) rng.nextBytes(x);
ba[--n] = x[0];
}
ba[--n] = 2;
ba[--n] = 0;
return new BigInteger(ba);
}如果您希望加密二进制数据,那么您可能必须修改此函数,以便它以您想要的方式转换输入。
下面是修改为接受十六进制字符串形式的二进制数据的pkcs1pad2()示例。如果您使用这个版本的pkcs1pad2(),那么您可以将CryptoJS.lib.WordArray转换为十六进制,并将该十六进制字符串传递给rsa.encrypt()。
function pkcs1pad2(hexPlaintext,n) {
if(n < hexPlaintext.length/2 + 11) {
alert("Message too long for RSA");
return null;
}
var ba = new Array();
var i = hexPlaintext.length;
while(i >= 2 && n > 0) {
ba[--n] = parseInt(hexPlaintext.slice(i-2,i),16);
i-=2;
}
ba[--n] = 0;
var rng = new SecureRandom();
var x = new Array();
while(n > 2) { // random non-zero pad
x[0] = 0;
while(x[0] == 0) rng.nextBytes(x);
ba[--n] = x[0];
}
ba[--n] = 2;
ba[--n] = 0;
return new BigInteger(ba);
}或者,您可以将其修改为直接获取WordArray并将其转换为JSBN使用的数组格式,但这将留给读者作为练习。
发布于 2013-11-19 17:57:54
从javascript转换为java的pkcs1pad2函数:
public BigInteger pkcs1pad2(String data,int keysize){
byte[] buffer=new byte[keysize];
Random rg=new Random();
if(keysize < data.length()+11)
return null;
int i = data.length() - 1;
while(i >= 0 && keysize > 0){
--keysize;
buffer[keysize] = (byte) data.charAt(i);
i--;
}
--keysize;
buffer[keysize] = 0;
while(keysize > 2){
--keysize;
buffer[keysize] = (byte) (rg.nextInt(254)+1);
}
--keysize;
buffer[keysize] = 2;
--keysize;
buffer[keysize] = 0;
return new BigInteger(buffer);
}rsa加密:
http://hc.apache.org/downloads.cgi
//you need httpcomponents-client-4.3.1-bin.zip from apache.org
//this contains working Base64 encoder!
import org.apache.commons.codec.binary.Base64;
public String encrypt(String data,String modulus,String exponent) throws UnsupportedEncodingException{
byte[] exp=Helper.hexToBytes(exponent.toCharArray());
byte[] mod=Helper.hexToBytes(modulus.toCharArray());
BigInteger expB=new BigInteger(exp);
BigInteger modB=new BigInteger(mod);
BigInteger data2=this.pkcs1pad2(data, (modB.bitLength()+7)>>3);
BigInteger data3=data2.modPow(expB, modB);
byte[] encoding = (new Base64()).encode(Helper.hexToBytes(data3.toString(16).toCharArray()));
return new String(encoding, "US-ASCII");
}和Helper.HexToBytes:
public static byte[] hexToBytes(char[] hex)throws IllegalArgumentException{
byte[] data = new byte[hex.length / 2];
for (int i = 0, j = 0; j < data.length; ++j){
int hi = Character.digit(hex[i++], 16);
int lo = Character.digit(hex[i++], 16);
if ((hi < 0) || (lo < 0))
throw new IllegalArgumentException();
data[j] = (byte) (hi << 4 | lo);
}
return data;
}https://stackoverflow.com/questions/16680631
复制相似问题