На стороне клиента (мобильное устройство) я шифрую пароль пользователя с помощью CryptoJS:
var lib_crypt = require('aes'); $.loginButton.addEventListener('click', function(e){ var key = lib_crypt.CryptoJS.enc.Hex.parse('bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3'); var iv = lib_crypt.CryptoJS.enc.Hex.parse('101112131415161718191a1b1c1d1e1f'); var encrypted = lib_crypt.CryptoJS.AES.encrypt($.passwordInput.value, key, { iv: iv }); var password_base64 = encrypted.ciphertext.toString(lib_crypt.CryptoJS.enc.Base64); return password_base64; });
На стороне сервера я хочу расшифровать его с помощью mcrypt_decrypt:
function decryptPassword($password) { $key = pack('H*', "bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3"); $ciphertext_dec = base64_decode($password); $iv_dec = "101112131415161718191a1b1c1d1e1f"; $ciphertext_dec = substr($ciphertext_dec, 16); $decryptedPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec); return trim($decryptedPassword); }
Я использую тот же ключ и IV, что я делаю неправильно?
Вы не делаете то же самое с обеих сторон.
Вы проанализировали IV в CryptoJS, но забыли сделать это в PHP:
$iv_dec = pack('H*', "101112131415161718191a1b1c1d1e1f");
Чтобы понять, что ваш IV ошибается, вы, вероятно, заметили, что первые 16 байтов являются тарабарщиной. Это происходит, когда IV ошибается. Обратите внимание, что CryptoJS использует режим CBC по умолчанию, поэтому IV влияет только на первый блок во время дешифрования. Удалить это:
$ciphertext_dec = substr($ciphertext_dec, 16);
Вы, наверное, заметили, что большинство открытых текстов не выходят правильно. Они заканчиваются с некоторыми странными повторенными символами в конце. Это дополнение PKCS # 7, которое по умолчанию применяется в CryptoJS. Вы должны удалить дополнение в PHP. Хорошо, что Maarten Bodewes предоставил правильное решение для копирования пасты для этого здесь .
trim()
может быть подходящим для ZeroPadding, но не тогда, когда используется правильная схема заполнения, подобная той, которая определена в PKCS # 7. Вы можете вообще удалить вызов trim()
, потому что это не полезно и может привести к неожиданному открытому тексту, поскольку нулевые байты и пробелы обрезаются с начала и до конца.
Здравствуйте,
для достижения этого следует учитывать использование ключа и iv с 32 шестнадцатеричными цифрами каждый, мне нужно было решить именно это, делая мои вещи, и вот так оно и есть
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"> </script> <script type="text/javascript"> //The key and iv should be 32 hex digits each, any hex digits you want, but it needs to be 32 on length each var key = CryptoJS.enc.Hex.parse("0123456789abcdef0123456789abcdef"); var iv = CryptoJS.enc.Hex.parse("abcdef9876543210abcdef9876543210"); /* if you wish to have a more friendly key, you can convert letters to Hex this way: var a = "D"; var hex_D = a.charCodeAt(0).toString(16); just to mention, if it were to binary, it would be: var binary_D = a.charCodeAt(0).toString(2); */ var secret = "Hi, this will be seen uncrypted later on"; //crypted var encrypted = CryptoJS.AES.encrypt(secret, key, {iv:iv}); //and the ciphertext put to base64 encrypted = encrypted.ciphertext.toString(CryptoJS.enc.Base64); //Assuming you have control on the server side, and know the key and iv hexes(we do), //the encrypted var is all you need to pass through ajax, //Let's follow with welcomed pure JS style, to reinforce one and other concept if needed var xh = new XMLHttpRequest(); xh.open("POST", "decrypt_in_php.php", true); xh.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xh.send("encrypted="+encodeURIComponent(encrypted)); </script>
И теперь получение и дешифрование в PHP
<?php //Here we have the key and iv which we know, because we have just chosen them on the JS, //the pack acts just like the parse Hex from JS $key = pack("H*", "0123456789abcdef0123456789abcdef"); $iv = pack("H*", "abcdef9876543210abcdef9876543210"); //Now we receive the encrypted from the post, we should decode it from base64, $encrypted = base64_decode($_POST["encrypted"]); $shown = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted, MCRYPT_MODE_CBC, $iv); echo $shown; //Although the decrypted is shown, there may be needed to trim and str_replace some \r \n \x06 \x05, if there is not a better "trim" way to do it though ?>
С этим мы вернем «Привет, это будет видно позже». 🙂