aes cfb 128 decrittografia / problema di crittografia tra Erlang e PHP

3

Aggiornamento 2: funziona

Grazie a Tom Leek per la sua risposta.

La modalità CFB di mycrypt per Rijndael utilizza un ciclo di feedback a 8 bit e non un ciclo di feedback della lunghezza della chiave / iv.

Devi forzarlo a usare l'intera lunghezza con il parametro ncfb . Confusamente questa non è una costante documentata nella libreria PHP Mcrypt: link

Le linee appropriate nel PHP ora assomigliano a questo:

$Crypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $Key, $Text, 'ncfb', $IV);

$Decrypt = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $Key, $Crypt, 'ncfb', $IV);

Aggiornato - vedi in basso

Sto cercando di ottenere e il sito di Erlang per scambiare informazioni tramite la crittografia aes_cfb_128 con un sito PHP. Sto scrivendo un'implementazione di test che dimostrerà che il PHP decodificherà ciò che Erlang crittografa e viceversa - ma sto avendo problemi.

Ecco la fonte PHP (mi scuso è un po 'scadente - il mio PHP non va bene - Sono un programmatore di Erlang):

<?php

function dump($String, $Bin) {
echo $String . " is " . ord($Bin[0]) . " " . ord($Bin[1]) . " " . ord($Bin[2]) . " " . ord($Bin[3]) . " " . ord($Bin[4]) . " " . ord($Bin[5]) . " " . ord($Bin[6]) . " " . ord($Bin[7]) . " " . ord($Bin[8]) . " " . ord($Bin[9]) . " " . ord($Bin[10]) . " " . ord($Bin[11]) . " " . ord($Bin[12]) . " " . ord($Bin[13]) . " " . ord($Bin[14]) . " " . ord($Bin[15]) . " " . ord($Bin[16]) . " " . ord($Bin[17]) . " " . ord($Bin[18]) . " " . ord($Bin[19]) . " " . ord($Bin[20]) . " " . ord($Bin[21]) . " " . ord($Bin[22]) . " " . ord($Bin[23]) . " " . ord($Bin[24]) . " " . ord($Bin[25]) . " " . ord($Bin[26]) . " " . ord($Bin[27]) . " " . ord($Bin[28]) . " " . ord($Bin[29]) . " " . ord($Bin[30]) . " " . ord($Bin[31]) ."\n";

}

$Key  = "abcdefghabcdefgh";
$IV   = "12345678abcdefgh";
$Text = "12345678123456781234567812345678";

$KeySize = strlen($Key) * 8;
$IVSize = strlen($IV) * 8;
$TextSize = strlen($Text) * 8;

$IVSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_NOFB);
echo "IVSze is " . $IVSize . " bytes or " . $IVSize * 8 . " bits\n";

$BlockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_NOFB);
echo "BlockSize is " . $BlockSize . " bytes or " . $IVSize * 8 . " bits\n";

$Crypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $Key, $Text, MCRYPT_MODE_NOFB, $IV);

$Decrypt = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $Key, $Crypt, MCRYPT_MODE_NOFB, $IV);

echo "Key   is   " . $Key  . " with size " . $KeySize  . "\n";
echo "IV    is   " . $IV   . " with size " . $IVSize   . "\n";
echo "Text  is   " . $Text . " with size " . $TextSize . "\n";
echo "Crypt is " . $Crypt  . "\n";
dump("Crypt", $Crypt);
echo "Decrypt is " . $Decrypt . "\n";
dump("Decrypt", $Decrypt);
?>

Ecco la fonte Erlang corrispondente:

-module(test_crypto).

-export([
         test/0
        ]).

test() ->
    Key  = <<"abcdefghabcdefgh">>,
    IV   = <<"12345678abcdefgh">>,
    Text = <<"12345678123456781234567812345678">> ,

    KeySize  = bit_size(Key),
    IVSize   = bit_size(IV),
    TextSize = bit_size(Text),

    io:format("Key  is ~p with size ~p~n", [Key, KeySize]),
    io:format("IV   is ~p with size ~p~n", [IV, IVSize]),
    io:format("Text is ~p with size ~p~n", [Text, TextSize]),

    Crypt = crypto:aes_cfb_128_encrypt(Key, IV, Text),
    io:format("Crypt is ~p~n", [Crypt]),
    B64 = base64:encode(Crypt),
    io:format("Crypt B64 is ~p~n", [B64]),

    Decrypt = crypto:aes_cfb_128_decrypt(Key, IV, Crypt),
    io:format("Decrypt is ~p~n", [Decrypt]),
    ok.

Ecco l'output di PHP:

gordon@hypernumbers:~/crypto$ php test_crypto.php
IVSze is 16 bytes or 128 bits
BlockSize is 16 bytes or 128 bits
Key   is   abcdefghabcdefgh with size 128
IV    is   12345678abcdefgh with size 16
Text  is   12345678123456781234567812345678 with size 256
Crypt is ��^DЭZ�!�)�y�9�������ht���'!
Crypt is 139 182 94 68 208 173 127 90 14 236 33 230 41 29 210 121 153 57 173 191 237 169 242 222 217 104 116 144 240 175 39 33
Decrypt is 12345678123456781234567812345678
Decrypt is 49 50 51 52 53 54 55 56 49 50 51 52 53 54 55 56 49 50 51 52 53 54 55 56 49 50 51 52 53 54 55 56

Ecco l'output di Erlang:

7> test_crypto:test().
Key  is <<"abcdefghabcdefgh">> with size 128
IV   is <<"12345678abcdefgh">> with size 128
Text is <<"12345678123456781234567812345678">> with size 256
Crypt is <<139,182,94,68,208,173,127,90,14,236,33,230,41,29,210,121,147,172,
           114,74,61,11,162,5,112,104,102,63,24,78,34,179>>
Crypt B64 is <<"i7ZeRNCtf1oO7CHmKR3SeZOscko9C6IFcGhmPxhOIrM=">>
Decrypt is <<"12345678123456781234567812345678">>
ok

Come puoi vedere entrambi i blocchi di codice si ciclano correttamente - ma non funzioneranno insieme perché non creano un testo cifrato identico.

I primi 16 byte del cypertext sono uguali - ma il secondo blocco di 16 byte è diverso.

So che questo algoritmo utilizza il primo blocco di output nella crittografia del secondo - quindi sospetto che ci sia un po 'di jiggery-pokery in corso tra il modo in cui il modulo di Erlang crypto lo sta facendo e il codice PHP mcrypt .

Aggiorna

Ho provato ad usare la modalità CFB in mycrypt ma credo che ci sia un differente feedback blockize o qualcosa del genere - e solo il primo carattere del cypertext era lo stesso. La modalità NOFB sembra essere correlata in qualche modo ed è la migliore che ho ottenuto finora ...

Se eseguo il PHP con la modalità CFB ottengo questo risultato:

~/crypto$ php test_crypto.php
IVSze is 16 bytes or 128 bits
BlockSize is 16 bytes or 128 bits
Key   is   abcdefghabcdefgh with size 128
IV    is   12345678abcdefgh with size 16
Text  is   12345678123456781234567812345678 with size 256
Crypt is ��*�b�ls�M����
                           ��ҮF��Y�=O
Crypt is 139 0 188 42 175 98 18 177 108 27 115 189 77 144 127 176 171 193 11 32 245 139 210 174 70 151 230 89 169 22 61 79
Decrypt is 12345678123456781234567812345678
Decrypt is 49 50 51 52 53 54 55 56 49 50 51 52 53 54 55 56 49 50 51 52 53 54 55 56 49 50 51 52 53 54 55 56

Ho provato ad ottenere aiuto su StackOverflow link ma ero soprattutto io a parlare con me stesso : (

    
posta Gordon Guthrie 02.02.2013 - 20:10
fonte

1 risposta

3

Il tuo codice PHP utilizza MCRYPT_MODE_NOFB durante la crittografia e la decrittografia; si utilizza la costante percentuale MCRYPT_MODE_CFB quando si ottengono le dimensioni IV e blocco, ma dopo si passa all'altra costante. Come spiegato su questa pagina , MCRYPT_MODE_NOFB non implementa CFB , ma un'altra modalità chiamata OFB . Da qui la discrepanza.

Aggiornamento: entrambe le modalità CFB e OFB hanno una "lunghezza di feedback". Quando usano un feedback di bit n (da 1 alla dimensione del blocco, cioè 128 con AES), crittografano i n bit di dati per invocazione del codice di blocco sottostante. L'utilizzo di una lunghezza di feedback inferiore alla dimensione del blocco rende quindi la crittografia più lenta, quindi nessuno lo fa.

Storicamente, le piccole lunghezze di feedback avevano lo scopo di aiutare i mezzi di trasporto che possono perdere sia i bit che la sincronizzazione - il tipo di descrizione che si applica a Il telegrafo di Samuel Morse . Con la retroazione a 1 bit, la decrittografia può "recuperare" dopo pochi bit, limitando così l'impatto dell'errore di trasmissione. Questa proprietà è abbastanza inutile su qualsiasi dispositivo elettronico che sia stato inventato sin dai tempi di Elvis Presley.

Inspiegabilmente (ma in genere), i progettisti di PHP hanno deciso di utilizzare OFB con feedback a 8 bit, riservando la costante alternativa ( NOFB ) per il feedback a blocco completo. È possibile che abbiano fatto lo stesso tipo di scelta strana per CFB.

Riepilogo: per CFB e OFB (che sono distinti l'uno dall'altro e non possono essere usati in modo intercambiabile), ci si deve preoccupare della "lunghezza del feedback" che non è necessariamente documentata con elevata chiarezza in varie librerie crittografiche. Sia la crittografia che la decrittografia devono utilizzare la stessa lunghezza di feedback per interoperare.

    
risposta data 02.02.2013 - 20:16
fonte

Leggi altre domande sui tag