2013-05-12 2 views
2

Я создаю открытый/закрытый ключ на сервере, отправив ключ клиенту JavaScript, где он шифрует пароль пользователя. Клиент отправляет пароль на сервер, а сервер использует закрытый ключ для его дешифрования, но пароль возвращается в нуль. Я подтвердил, что все значения, подтверждающие ситуацию, верны, так что это что-то с шифрованием/расшифровкой. Где я иду не так?Encrypt with Cryptico.js, расшифровать с помощью OpenSSL

Возможно, cryptico.js несовместим с php openssl?

Библиотека Информация:

https://github.com/wwwtyro/cryptico

http://www.php.net/manual/en/function.openssl-pkey-new.php

Вот соответствующие фрагменты кода:

PHP - создать открытый/закрытый ключ

$config = array(
    "digest_alg" => "sha512", 
    "private_key_bits" => 2048, 
    "private_key_type" => OPENSSL_KEYTYPE_RSA, 
); 

// Create the private and public key 
$res = openssl_pkey_new($config); 

// Extract the private key from $res to $privateKey 
openssl_pkey_export($res, $privateKey); 

// Extract the public key from $res to $publicKey 
$publicKey = openssl_pkey_get_details($res); 
$publicKey = $publicKey["key"]; 

JavaScript - клиент шифрует данные открытым ключом.

var xhr = new XMLHttpRequest(); 
var data = new FormData(); 
xhr.open('POST', '/signUp2.php'); 
data.append('user', User); 

var encryptedPassword = cryptico.encrypt(password, localStorage["publicKey"]); 
data.append('password', encryptedPassword.cipher); 

xhr.onreadystatechange = function() 
{ 
    if(xhr.readyState == 4 && xhr.status == 200) 
    { 
     var jsonArray = JSON.parse(xhr.responseText); 

     if(jsonArray[0] == "0") 
     { 
      alert("Account created. You may now sign in."); 
     } 
     else 
      alert("Error Code: " + jsonArray[0]); 
    } 
} 
xhr.send(data); 

PHP - recieves сервера зашифрован пароль и пытается установить расшифровывать безуспешно

openssl_private_decrypt($encryptedPassword, $decryptedPassword, $row[1]); 
+0

Вы используете SHA512 на стороне сервера. Тем не менее, я прочитал, что собственный Javascript поддерживает только 256-битное шифрование AES и в документации, он приводит пример совместимости с aes 256bit Keys: http://code.google.com/p/crypto-js/#Interoperability – mondjunge

ответ

4

cryptico.js могли бы работать с OpenSSL, но мы должны изменить его немного.

он не принимает прямого доступа к открытому ключу в формате pem (который открывает использование). мы должны извлечь «N» и «е» часть открытого ключа в сторону PHP:

$key = openssl_pkey_new(array( 
    'private_key_bits' => 1024, 
    'private_key_type' => OPENSSL_KEYTYPE_RSA, 
    'digest_alg' => 'sha256' 
)); 

$detail = openssl_pkey_get_details($key); 
$n = base64_encode($detail['rsa']['n']); 
$e = bin2hex($detail['rsa']['e']); 

также, cryptico.js жёстко закодировал «е» части открытого ключа (см определение publicKeyFromString в апи .js), так что мы должны это исправить:

my.publicKeyFromString = function(string) 
{ 
    var tokens = string.split("|"); 
    var N = my.b64to16(tokens[0]); 
    var E = tokens.length > 1 ? tokens[1] : "03"; 
    var rsa = new RSAKey(); 
    rsa.setPublic(N, E); 
    return rsa 
} 

теперь мы можем шифровать строки:

var publicKey = "{$n}|{$e}", 
    encrypted = cryptico.encrypt("plain text", publicKey); 

работа еще не закончена. результат cryptico.encrypt НЕ просто зашифрован RSA. Действительно, он был объединен в две части: ключ aes, зашифрованный RSA, и шифр простого текста, зашифрованного этим ключом AES. если нам нужно только RSA, мы могли бы изменить my.encrypt:

my.encrypt = function(plaintext, publickeystring, signingkey) 
{ 
    var cipherblock = ""; 
    try 
    { 
    var publickey = my.publicKeyFromString(publickeystring); 
    cipherblock += my.b16to64(publickey.encrypt(plaintext)); 
    } 
    catch(err) 
    { 
    return {status: "Invalid public key"}; 
    } 
    return {status: "success", cipher: cipherblock}; 
} 

теперь мы способны расшифровать шифр с OpenSSL:

$private = openssl_pkey_get_private("YOUR PRIVATE KEY STRING IN PEM"); 
// $encrypted is the result of cryptico.encrypt() in javascript side 
openssl_private_decrypt(base64_decode($encrypted), $decrypted, $private); 
// now $decrypted holds the decrypted plain text 
+0

Это отлично работало для меня, спасибо! – citizenslave

+0

Я получаю пустую строку для '$ e = bin2hex ($ detail ['rsa'] ['e']);'. Этого можно ожидать вообще? – JVE999

+0

@ JVE999 Возможно, ваше расширение openssl установлено неправильно? если php не может найти openssl.conf, он не сможет генерировать ключи, но все же способен делать шифрование/дешифрование. проверьте http: //us1.php.net/manual/en/openssl.installation.php – Nowgoo