2013-05-21 3 views
2

J'utilise JSBN pour crypter/décrypter des données en utilisant des paires de clés publiques/privées. Cela fonctionne très bien pour les données de texte, y compris les chaînes hexadécimales.Comment crypter des clés Crypto-JS avec JSBN?

Mon problème est maintenant j'ai des données binaires, en particulier Crypto-JS Word Arrays, que j'ai besoin de crypter avec une clé publique et d'envoyer vers une autre plate-forme.

considèrent donc ceci:

var key = CryptoJS.lib.WordArray.random(256/8); 
var rsa = new RSAKey(); 
rsa.setPublic(modulus, exponent); 
var encrypted_key = rsa.encrypt(key.toString()); 

Cela fonctionne, mais cela signifie « encrypted_key » est enfait une chaîne hexagonale qui a été chiffré, pas la clé réelle. J'ai besoin de crypter la clé actuelle.

Je vois deux défis ici:

1) Je ne suis pas sûr à 100% comment obtenir les octets réels d'un CryptoJS.lib.WordArray - même si cela ne semble pas totalement insurmontable.

2) Je ne sais pas s'il est même possible de chiffrer des données binaires en utilisant JSBN. J'adorerais des pointeurs pour comprendre comment le faire.

Des pensées?

Répondre

2

La bibliothèque JSBN contient une fonction, à savoir pkcs1pad2(), dans laquelle elle convertit le texte en valeurs numériques à l'aide de la fonction charCodeAt() de JavaScript. Vous verrez que le code de conversion dans le premier temps() boucle:

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); 
} 

Si vous souhaitez crypter les données binaires alors vous aurez probablement à modifier cette fonction il convertit l'entrée de la manière que vous voulez . Voici un exemple de pkcs1pad2() modifié pour accepter des données binaires sous la forme d'une chaîne hexadécimale. Si vous utilisez cette version de pkcs1pad2() alors vous pouvez convertir votre CryptoJS.lib.WordArray en hexadécimal et transmettre cette chaîne hexadécimale à 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); 
} 

Sinon, vous pouvez le modifier pour prendre le WordArray directement et le convertir au format de tableau qui est utilisé par JSBN, mais je vais laisser cela comme un exercice pour le lecteur.

+0

Bri lliant! Bien sûr, l'extrémité opposée - pkcs1unpad2 - devra être modifiée de manière similaire (ou étendue). –

0

la fonction de conversion à partir de pkcs1pad2 javascript de java:

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); 
} 

la encription 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"); 
} 

et les 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; 
} 
Questions connexes