2016-04-21 44 views
7

ho una password che è cifrare da JavaScript tramiteCome per decriptare la password da JavaScript CryptoJS.AES.encrypt (password, password) in Python

var password = 'sample' 
    var passphrase ='sample_passphrase' 
    CryptoJS.AES.encrypt(password, passphrase) 

Poi ho cercato di decifrare la password viene da JavaScript in Python :

from Crypto.Cipher import AES 
    import base64 

    PADDING = '\0' 

    pad_it = lambda s: s+(16 - len(s)%16)*PADDING 
    key = 'sample_passphrase' 
    iv='11.0.0.101'  #------> here is my question, how can I get this iv to restore password, what should I put here? 
    key=pad_it(key)  #------> should I add padding to keys and iv? 
    iv=pad_it(iv)   ## 
    source = 'sample' 
    generator = AES.new(key, AES.MODE_CFB,iv) 
    crypt = generator.encrypt(pad_it(source)) 
    cryptedStr = base64.b64encode(crypt) 
    print cryptedStr 
    generator = AES.new(key, AES.MODE_CBC,iv) 
    recovery = generator.decrypt(crypt) 
    print recovery.rstrip(PADDING) 

ho controllato JS dalla console del browser, mostra IV in CryptoJS.AES.encrypt(password, passphrase) è un oggetto con alcuni attributi (come sigBytes:16, words: [-44073646, -1300128421, 1939444916, 881316061]). Sembra generato casualmente.

da una pagina web, mi dice che JS ha due modi per crittografare la password (reference link):

  • a. crypto.createCipher(algorithm, password)
  • b. crypto.createCipheriv(algorithm, key, iv)

Quello che ho visto in JavaScript dovrebbe essere l'opzione a. Tuttavia, solo l'opzione b è equivalente a AES.new() in python.

Le domande sono:

  1. Come posso ripristinare la password in Python senza modificare il codice JavaScript?

  2. Se ho bisogno di IV in Python, come posso ottenerlo dalla password utilizzata in JavaScript?

+0

CryptoJS AES ha come impostazione predefinita la modalità CBC, quindi non è necessaria la modalità CBF in python. AES.encrypt restituisce anche un oggetto. con toString() si ottiene un blob con codifica Base64 contenente sale, iv e message. Tutti loro hanno bisogno di separare il feed finale in Python. Inoltre, tieni presente che la password e la chiave sono due cose diverse. – SKR

+0

Grazie, basta modificare la chiave in sample_passphrase, quindi sarà più chiaro. ma cosa succede se non riesco a ottenere l'output toString()? È diventato un lavoro impossibile? @SKR – Bing

+0

quindi vuoi dire che non hai alcun controllo su tutto il js? Come continua il codice js? cosa succede con l'oggetto restituito da criptare? Hai bisogno di ottenere il sale e iv fuori dal js in qualche modo. O vuoi semplicemente "deridere" il comportamento di js e generare un messaggio crittografato simile per una API esterna o qualcosa del genere? – SKR

risposta

10

Sarà necessario implementare OpenSSL di EVP_BytesToKey, perché è quello che utilizza CryptoJS per derivare la chiave e IV della password fornita, ma pycrypto supporta solo il tasto + IV tipo di crittografia. CryptoJS genera anche un salt casuale che deve anche essere inviato al server. Se l'oggetto ciphertext viene convertito in una stringa, utilizza automaticamente un formato compatibile OpenSSL che include il sale casuale.

var data = "Some semi-long text for testing"; 
 
var password = "some password"; 
 
var ctObj = CryptoJS.AES.encrypt(data, password); 
 
var ctStr = ctObj.toString(); 
 

 
out.innerHTML = ctStr;
<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/aes.js"></script> 
 
<div id="out"></div>

uscita possibile:

U2FsdGVkX1 + ATH716DgsfPGjzmvhr + 7 + pzYfUzR + 25u0D7Z5Lw04IJ + LmvPXJMpz

CryptoJS default è 256 bit dimensione della chiave AES, PKCS # 7 padding e modalità CBC. AES ha una dimensione di blocco di 128 bit che è anche la dimensione IV. Ciò significa che dobbiamo richiedere 32 + 16 = 48 byte da EVP_BytesToKey. Ho trovato un'implementazione semi-funzionale here e l'ho estesa ulteriormente.

Ecco il completo Python (testato con 2.7 e 3.4) il codice, che è compatibile con CryptoJS:

from Crypto import Random 
from Crypto.Cipher import AES 
import base64 
from hashlib import md5 

BLOCK_SIZE = 16 

def pad(data): 
    length = BLOCK_SIZE - (len(data) % BLOCK_SIZE) 
    return data + (chr(length)*length).encode() 

def unpad(data): 
    return data[:-(data[-1] if type(data[-1]) == int else ord(data[-1]))] 

def bytes_to_key(data, salt, output=48): 
    # extended from https://gist.github.com/gsakkis/4546068 
    assert len(salt) == 8, len(salt) 
    data += salt 
    key = md5(data).digest() 
    final_key = key 
    while len(final_key) < output: 
     key = md5(key + data).digest() 
     final_key += key 
    return final_key[:output] 

def encrypt(message, passphrase): 
    salt = Random.new().read(8) 
    key_iv = bytes_to_key(passphrase, salt, 32+16) 
    key = key_iv[:32] 
    iv = key_iv[32:] 
    aes = AES.new(key, AES.MODE_CBC, iv) 
    return base64.b64encode(b"Salted__" + salt + aes.encrypt(pad(message))) 

def decrypt(encrypted, passphrase): 
    encrypted = base64.b64decode(encrypted) 
    assert encrypted[0:8] == b"Salted__" 
    salt = encrypted[8:16] 
    key_iv = bytes_to_key(passphrase, salt, 32+16) 
    key = key_iv[:32] 
    iv = key_iv[32:] 
    aes = AES.new(key, AES.MODE_CBC, iv) 
    return unpad(aes.decrypt(encrypted[16:])) 


password = "some password".encode() 
ct_b64 = "U2FsdGVkX1+ATH716DgsfPGjzmvhr+7+pzYfUzR+25u0D7Z5Lw04IJ+LmvPXJMpz" 

pt = decrypt(ct_b64, password) 
print("pt", pt) 

print("pt", decrypt(encrypt(pt, password), password)) 

codice simile può essere trovato nelle mie risposte per Java e PHP.

JavaScript La crittografia AES nel browser senza HTTPS è semplice offuscamento e non fornisce alcuna protezione reale, poiché la chiave deve essere trasmessa insieme al testo cifrato.

+0

Ho provato questo, funziona perfettamente. Molte grazie. Non so molto su come crittografare e decodificare lavorare con queste opzioni, se si può contrassegnare alcuni collegamenti di riferimento posso ottenere queste informazioni, che sarà molto apprezzato. – Bing

+0

Non sono sicuro di capire quali riferimenti stai cercando. Se stai parlando di come so tutto questo, allora il modo più semplice sarebbe semplicemente prendere il codice sorgente non ancora risolto e leggerlo. –

+0

Sì, intendo come ottenere queste informazioni. Controllerò un po 'di codice. Grazie. – Bing