Алгоритм шифрования, возвращающий разные значения в php и javascript

В PHP

<?php
  $token = '[email protected]|ts=1412917909|hash=r1xWbgfHUxDLlppGYuOKQJdIM1MTrkryEArkMQx9ERw=|url=http://myintranet.com';
  $key = 'a1cbbb6eb5cb2c1c27a9f02a4434d3af';
  $token =  mb_convert_encoding( $token ,'UTF-16LE' );
  $blockSize = 16;
  $pad = $blockSize - (strlen($token) % $blockSize);
  $token .= str_repeat(chr($pad), $pad);
  $token = mcrypt_encrypt(MCRYPT_RIJNDAEL_128,$key, $token, MCRYPT_MODE_CBC, $iv);

  $token = base64_encode($token);
  echo "\n This is the token $token \n";
?>

Вывод -:

 This is the token TXz3UEgAdjGhyriNGcMJBUk4QcW3dA7rttzjbKztw19X8bSIMDZt8s6uSQy2OP5QcSpJuReKv73wFXzPyCXt05CNY6XWlx9Lfrv6Nosj0+4mHdD7/Wvx0QWqxuuv5qv4sgtgSif59Wy/ZAoYhfH8yzN/3hWnx6zzOrV6jxyDttmffk1zcBwtJ3X41mMVbPLOd1/2K3ZYxCcJ1VxESFDNB4N1okvGMRkCM0tL77oZiKv+n6CP9FEgKivCfvytFB8JWc9K++8vbLdV/iGgkEa7h0pfAZtYpryQQjFzqLx8NSQ= 

В Javascript

'use strict';

var CryptoJS = require("crypto-js");

String.prototype.repeat = function( num )
{
    return new Array( num + 1 ).join( this );
}

function encodeUTF16LE(str) {
    var out, i, len, c;
    var char2, char3;

    out = "";
    len = str.length;
    i = 0;
    while(i < len) {
        c = str.charCodeAt(i++);
        switch(c >> 4)
        {
          case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
            // 0xxxxxxx
            out += str.charAt(i-1);
            break;
          case 12: case 13:
            // 110x xxxx   10xx xxxx
            char2 = str.charCodeAt(i++);
            out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
            out += str.charAt(i-1);
            break;
          case 14:
            // 1110 xxxx  10xx xxxx  10xx xxxx
            char2 = str.charCodeAt(i++);
            char3 = str.charCodeAt(i++);
            out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
            break;
        }
    }

    var byteArray = new Uint8Array(out.length * 2);
    for (var i = 0; i < out.length; i++) {
        byteArray[i*2] = out.charCodeAt(i); // & 0xff;
        byteArray[i*2+1] = out.charCodeAt(i) >> 8; // & 0xff;
    }

    return String.fromCharCode.apply( String, byteArray );
}

var token = '[email protected]|ts=1412917909|hash=r1xWbgfHUxDLlppGYuOKQJdIM1MTrkryEArkMQx9ERw=|url=http://myintranet.com';
var key = 'a1cbbb6eb5cb2c1c27a9f02a4434d3af';
var blockSize = 16;
token =  encodeUTF16LE(token);
var pad = blockSize - (token.length % blockSize);

token = token + (String.fromCharCode(pad)).repeat(pad);

token = CryptoJS.AES.encrypt(token, key,
    {   iv: iv,
        mode: CryptoJS.mode.CBC
    });

console.log("\n This is the token " + token + "\n");

token = token.ciphertext.toString(CryptoJS.enc.Base64);
console.log("\n This is the token " + token + "\n");

Вывод

This is the token U2FsdGVkX19iQjVHkx/vmhljCsRyTBUA0QFJ8I+pPvxAa2dK6iO4r9FUw2Um2j0H+iyXZ/G0UO0fhJTFzfJEfS1cMfAaq0Z7UBUpVhtrH5IArr2F3BI6yWC8Kpo4ZimyW+xnWp0BYUpLUNQTLsFooiIqPHv3s9HHMe3k0altm6ou1pAKaIr8IAY1OzIDTbaRO55mPf0rU6Z2XTLGR6kYoAx9Lk4dZ3RA66cynXWFMuHznL0fik3phZ8cUiKd/Twquil97YHT+CB/1ulxEBD17VQvnsCJI1lYNn9dyWAUG96KMgGk3jFxiW9eRzV5Poywnt0QNaRpmZiG41KNFmtMtw==


This is the token GWMKxHJMFQDRAUnwj6k+/EBrZ0rqI7iv0VTDZSbaPQf6LJdn8bRQ7R+ElMXN8kR9LVwx8BqrRntQFSlWG2sfkgCuvYXcEjrJYLwqmjhmKbJb7GdanQFhSktQ1BMuwWiiIio8e/ez0ccx7eTRqW2bqi7WkApoivwgBjU7MgNNtpE7nmY9/StTpnZdMsZHqRigDH0uTh1ndEDrpzKddYUy4fOcvR+KTemFnxxSIp39PCq6KX3tgdP4IH/W6XEQEPXtVC+ewIkjWVg2f13JYBQb3ooyAaTeMXGJb15HNXk+jLCe3RA1pGmZmIbjUo0Wa0y3

Я думаю, проблема в CryptoJS.AES.encrypt, где я не передаю ему правильную конфигурацию?

На самом деле застрял на этом, поэтому, если у вас есть какие-либо предложения, я хотел бы знать.


person Pratik Bothra    schedule 10.10.2014    source источник
comment
Что такое $key и key? PHP mcrypt и CryptoJS по-разному обрабатывают ввод ключа: stackoverflow.com/a/24343162/371137   -  person Perseids    schedule 10.10.2014
comment
@Perseids - Только что обновил значение ключа. Ключ генерируется на основе алгоритма, но, по крайней мере, в обоих случаях он одинаков. Я использую MCRYPT_RIJNDAEL_128, поэтому я думаю, что это можно сделать, но я очень не уверен в том, как работает заполнение.   -  person Pratik Bothra    schedule 10.10.2014


Ответы (1)


В обоих случаях ключ обрабатывается не так, как вы ожидаете. 'a1cbbb6eb5cb2c1c27a9f02a4434d3af' - это шестнадцатеричное представление 16-байтового (= 128-битного) ключа, которое может использоваться для AES128.

mcrypt не знает, что он получает шестнадцатеричное представление, и рассматривает его как 32-байтовую строку и - IIRC - отбрасывает все, кроме первых 16 байтов ('a1cbbb6eb5cb2c1c'). Вам нужно распаковать ключ, чтобы получить необработанные байты: $key=pack('H*', 'a1cbbb6eb5cb2c1c27a9f02a4434d3af').

CryptoJS также не знает, что он представлен в шестнадцатеричном представлении ключа, и вместо этого рассматривает его как пароль , который используется в качестве входных данных для PBKDF2. У библиотеки есть свои собственные подпрограммы unhexlify: var key = CryptoJS.enc.Hex.parse('a1cbbb6eb5cb2c1c27a9f02a4434d3af'); Полученные WordArray будут обработаны от CryptoJS как ввод двоичного ключа.

person Perseids    schedule 10.10.2014