Что нового

[Криптография] Функции шифрования AES128, AES192, AES256 (CBC) совместимые с PHP OpenSSL

inververs

AutoIT Гуру
Сообщения
2 135
Репутация
462
Категория: Кодирование, Шифрование, Microsoft Cryptographic Service Provider, OpenSSL, openssl_encrypt, openssl_decrypt, php, AES, Rijndael

Описание:
Библиотека предназначена для шифрования текста симметричным алгоритмом блочного шифрования (размер блока 128 бит, ключ 128/192/256 бит) с использованием пользовательского пароля.
Функции используют для шифрования Microsoft Cryptographic Service Provider в AutoIt и стандартную библиотеку OpenSSL в PHP.

Особенности:
  • Библиотека не имеет внешних зависимостей.
  • Работает с текстом в кодировке UTF-8
  • Шифрованные данные преобразовывает в формат Base64 для удобной передачи по сети
  • Использует Microsoft API для шифрования/дешифрирование
  • Ключ формируется на основе пользовательского пароля и алгоритма SHA256
  • В отличии от _Crypt_DecryptData использует начальный вектор инициализации (Initialization vector (IV))

Функции:
Код:
;Функция шифрования (Данные, пароль, алгоритм)
_CryptPhp_EncryptString($sData, $sCode[, $sAlgo = 'AES-192-CBC'])
;Функция дешифрирования (Данные, пароль, алгоритм)
_CryptPhp_DecryptString($sData, $sCode[, $sAlgo = 'AES-192-CBC'])



Пример:
Код:
#include "CryptPhp.au3"
Local $sData = 'A pointer to a DWORD value that indicates the length of the pbData buffer.'
Local $sCode = '123_MyPassword!'

Local $sEncrypted = _CryptPhp_EncryptString($sData, $sCode)
ConsoleWrite(@error & ' ' & @extended & ' ' & $sEncrypted & @CRLF)

Local $sDecrypted = _CryptPhp_DecryptString($sEncrypted, $sCode)
ConsoleWrite(@error & ' ' & @extended & ' ' & $sDecrypted & @CRLF)


PHP класс:
PHP:
class CryptPhp
{
    private $cipherAlgorithm;
    private $hashAlgorithm;
    private $iv_num_bytes;

    public function __construct($cipherAlgorithm = 'AES-192-CBC')
    {
        $this->cipherAlgorithm = $cipherAlgorithm;
        $this->hashAlgorithm = 'SHA256';
        $this->iv_num_bytes = openssl_cipher_iv_length($cipherAlgorithm);

        if ( ! in_array($cipherAlgorithm, openssl_get_cipher_methods(true))) {
            throw new \Exception("CryptPhp:: - unknown cipher algo {$cipherAlgorithm}");
        }

        if ( ! in_array($this->hashAlgorithm, openssl_get_md_methods(true))) {
            throw new \Exception("CryptPhp:: - unknown hash algo {$this->hashAlgorithm}");
        }
    }

    public function encryptString($in, $key)
    {
        $iv = mcrypt_create_iv($this->iv_num_bytes, MCRYPT_DEV_URANDOM);
        $hash = openssl_digest($key, $this->hashAlgorithm, true);
        $encrypted = openssl_encrypt($in, $this->cipherAlgorithm, $hash, OPENSSL_RAW_DATA, $iv);
        if ($encrypted === false) {
            throw new \Exception('CryptPhp::encryptString - Encryption failed: ' . openssl_error_string());
        }
        return base64_encode($iv . $encrypted);
    }

    public function decryptString($in, $key)
    {
        $raw = base64_decode($in);
        if (strlen($raw) < $this->iv_num_bytes) {
            throw new \Exception('CryptPhp::decryptString - ' .
                'data length ' . strlen($raw) . " is less than iv length {$this->iv_num_bytes}");
        }
        $iv = substr($raw, 0, $this->iv_num_bytes);
        $raw = substr($raw, $this->iv_num_bytes);
        $hash = openssl_digest($key, $this->hashAlgorithm, true);
        $res = openssl_decrypt($raw, $this->cipherAlgorithm, $hash, OPENSSL_RAW_DATA, $iv);
        if ($res === false) {
            throw new \Exception('CryptPhp::decryptString - decryption failed: ' . openssl_error_string());
        }
        return $res;
    }
}
PHP пример:
PHP:
$data = 'A pointer to a DWORD value that indicates the length of the pbData buffer.';
$code = '123_MyPassword!';

$crypt = new CryptPhp();
$encrypted = $crypt->encryptString($data, $code);
$decrypted = $crypt->decryptString($encrypted, $code);

echo "encrypted => $encrypted\n";
echo "decrypted => $decrypted\n";
Примечание: Для Windows XP вместо SHA256 используйте SHA1

Файл: Скачать CryptPhp.au3

Источник: autoit-script.ru
Автор(ы): inververs
 

Garrett

Модератор
Локальный модератор
Сообщения
3 999
Репутация
963
inververs
1. Я так понимаю, PHP код для примера совместимости?
2. Почему CryptPhp? Как следствие, вытекающие из пункта 1?
 
Автор
inververs

inververs

AutoIT Гуру
Сообщения
2 135
Репутация
462
Garrett
Да, тут php для того, что бы показать, как это делать именно на php, что бы полученный результат был совместим.
Я показал необходимый минимум для этих функций, где используется вектор инициализации, хэширование ключа, пароль и сам текст.
Результат я отдаю как iv + данные и кодирую в base64, т.к везде(в любом языке) должны быть функции для работы с ним.

Хочу отметить, что подходы к шифрованию текста могут отличаться. Например, в результат может быть подмешена соль, или ключ может быть сформирован по другим алгоритмам, поэтому нужно обращать внимание на используемый подход в вашем фреймворке или библиотеке.
 
A

Alofa

Гость
Спасибо, возьму в копилку.
Но ИМХО, я думаю куда привычней и правильней задавать алгоритмы "AES-128-CBC", "AES-192-CBC" и "AES-256-CBC" объявленными константами.
 
Автор
inververs

inververs

AutoIT Гуру
Сообщения
2 135
Репутация
462
Alofa
Вы можете в код дописать так:
Код:
Switch $sAlgo
		Case 'AES-128-CBC', 0x0000660e
			$iAlg = 0x0000660e ;$CALG_AES_128
...

и тогда алгоритм можно будет передать константой
 

joiner

Модератор
Локальный модератор
Сообщения
3 012
Репутация
502
inververs, :ok:
OffTopic:
было бы замечательно, если бы в описаниях был и русский язык.
 
Автор
inververs

inververs

AutoIT Гуру
Сообщения
2 135
Репутация
462
joiner
:rolleyes: хотелось бы. Но как 2 языка сделать?
 

Garrett

Модератор
Локальный модератор
Сообщения
3 999
Репутация
963
inververs
OffTopic:

[?]
хотелось бы. Но как 2 языка сделать?
Я задумывался над этим вопросом, но так всё в тестовых вариантах и осталось. С обновлением GUI у меня что-то не клеилось (не менялся язык после перерисовки gui, только после перезагрузки программы).

Задумка следующая, создать программу для просмотра UDF и желающий сделать перевод может редактировать языковой файл.
Как вариант можно попробовать.
 

Vanguger

Чайник
Сообщения
48
Репутация
0
У меня указанный код почему-то не расшифровывает. Выдаёт:

Код:
0 0 J5kT/MPbHFvqCGEzJrm2EVt73JFGlkHaol7M3symEpdYhggHAnlUhNIqptmnVjt47FyeO7bk6SvuP9l1xpvomBXB1XPLAf3fN5sJhRrZbA1t+RO9s5fyLz+0b5Wjg7Jc
9 0 False
В библиотеке это следующие строки:
Код:
;Determinate buffer size
		$aRet = DllCall($hAdvapi32, "bool", "CryptDecrypt", "handle", $hKey, "handle", 0, "bool", True, "dword", 0, _
			"struct*", Null, "dword*", BinaryLen($bEncrypted))
		If @error Or Not $aRet[0] Then ExitLoop SetError(9, @error, 1)


Подскажите пожалуйста с чем это связано, как исправить?
 
Автор
inververs

inververs

AutoIT Гуру
Сообщения
2 135
Репутация
462
Вот этот код можете комментировать
Код:
;Determinate buffer size
;~ 		$aRet = DllCa1ll($hAdvapi32, "bool", "CryptDecrypt", "handle", $hKey, "handle", 0, "bool", True, "dword", 0, _
;~ 			"struct*", Null, "dword*", BinaryLen($bEncrypted))
;~ 		If @error Or Not $aRet[0] Then ExitLoop SetError(9, @error, 1)

А чуть ниже поменяйте так:
Код:
;Create buffer
		Local $hBuffCipherText = DllStructCreate('byte[' & BinaryLen($bEncrypted) & ']')
		DllStructSetData($hBuffCipherText, 1, $bEncrypted)

		;Decrypt
		$aRet = DllCall($hAdvapi32, "bool", "CryptDecrypt", "handle", $hKey, "handle", 0, "bool", True, "dword", 0, _
			"struct*", $hBuffCipherText, "dword*", DllStructGetSize($hBuffCipherText))
		If @error Or Not $aRet[0] Then ExitLoop SetError(10, @error, 1)

Так должно заработать
 

Vanguger

Чайник
Сообщения
48
Репутация
0
Появляется msgbox с заголовком 87 и текстом 80 Параметр задан неверно. У меня Win7.


Добавлено:
Сообщение автоматически объединено:

inververs сказал(а):
Вот этот код можете комментировать
Код:
;Determinate buffer size
;~ 		$aRet = DllCa1ll($hAdvapi32, "bool", "CryptDecrypt", "handle", $hKey, "handle", 0, "bool", True, "dword", 0, _
;~ 			"struct*", Null, "dword*", BinaryLen($bEncrypted))
;~ 		If @error Or Not $aRet[0] Then ExitLoop SetError(9, @error, 1)

А чуть ниже поменяйте так:
Код:
;Create buffer
		Local $hBuffCipherText = DllStructCreate('byte[' & BinaryLen($bEncrypted) & ']')
		DllStructSetData($hBuffCipherText, 1, $bEncrypted)

		;Decrypt
		$aRet = DllCall($hAdvapi32, "bool", "CryptDecrypt", "handle", $hKey, "handle", 0, "bool", True, "dword", 0, _
			"struct*", $hBuffCipherText, "dword*", DllStructGetSize($hBuffCipherText))
		If @error Or Not $aRet[0] Then ExitLoop SetError(10, @error, 1)

Так должно заработать
Да, так заработало! Благодарю Вас!
В чём же тут была причина, можете рассказать?
 

robinhood3

Чайник
Сообщения
1
Репутация
0
привет, я пытаюсь скачать файл "CryptPhp.au3" ", но это возвращает меня к началу форума. Вы можете мне помочь?
 
Верх