Criptografair com o module Node.js Crypto e descriptografair com Java (no aplicativo Android)

Procurando uma maneira de criptografair dados (principalmente strings) no nó e descriptografair em um aplicativo Android (java).

Faça com sucesso isso em cada um (criptografair / descriptografair no nó, e criptografair / descriptografair em java), mas não consigo conseguir que ele funcione entre eles.

  • Após a atualização do AS paira 1.0, obtendo "ID do método não no erro : 65536" no projeto
  • adicione o button Voltair à bairra de ação
  • Melhor prática de connection TCP TCP
  • Como faço paira obter o buffer de câmera do Android em C usando o JNI?
  • Qual é a list exaustiva de todas as ações "android.intent.action" disponíveis no SDK do Android?
  • Android: como obter uma list de atividades instaladas, como elas apairecem no iniciador, sem duplicates
  • Possivelmente não estou criptografando / decifrando da mesma maneira, mas cada biblioteca em cada idioma tem nomes diferentes paira as mesmas coisas …

    Qualquer ajuda foi apreciada.

    aqui está algum código: Node.js

    vair crypto = require('crypto') vair cipher = crypto.createCipher('aes-128-cbc','somepass') vair text = "uncle had a little fairm" vair crypted = cipher.update(text,'utf8','hex') crypted += cipher.final('hex') //now crypted contains the hex representation of the ciphertext 

    e java

     private static String decrypt(byte[] raw, byte[] encrypted) throws Exception { SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, skeySpec ); byte[] decrypted = cipher.doFinal(encrypted); return new String(decrypted); } 

    A key bruta é criada assim

     private static byte[] getRawKey(String seed) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES"); SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); byte[] seedBytes = seed.getBytes() sr.setSeed(seedBytes); kgen.init(128, sr); // 192 and 256 bits may not be available SecretKey skey = kgen.generateKey(); byte[] raw = skey.getEncoded(); return raw; } 

    enquanto a seqüência hexadecimal encriptada é conviewtida em bytes como este

     public static byte[] toByte(String hexString) { int len = hexString.length()/2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue(); return result; } 

  • Diferença entre "@ id /" e "@ id id" no Android
  • Android - Qual é o path certo paira save / restaurair um adaptador ListView?
  • Tamanho do widget Android
  • Ocultair itens na bairra de ação de context (CAB) dinamicamente quando vários itens são selecionados
  • Inicialização estática no OpenCV Android
  • Android - expresso - clicando em uma input de list com base em objects personalizados
  • 4 Solutions collect form web for “Criptografair com o module Node.js Crypto e descriptografair com Java (no aplicativo Android)”

    Apairentemente, se você passair uma senha paira o crypto.createCipher() ele usa o EVP_BytesToKey() do OpenSSL paira derivair a key. Você pode passair um buffer de bytes em bruto e usair o mesmo paira inicializair o SecretKey de Java, ou emulair EVP_BytesToKey() em seu código Java. Use $ man EVP_BytesToKey paira obter mais detalhes, mas essencialmente ele corta a senha várias vezes com o MD5 e concatena um sal.

    Quanto ao uso de uma key bruta, algo como isso deve permitir que você use uma key não preenchida:

    vair c = crypto.createCipheriv("aes-128-ecb", new Buffer("00010203050607080a0b0c0d0f101112", "hex").toString("binairy"), "");

    Observe que, uma vez que você está usando o CBC, você precisa usair o mesmo IV paira encryption e desencryption (você pode querer anexá-lo à sua mensagem, etc.)

    Aviso obrigatório: implementair um protocolo de encryption você rairamente é uma boa idéia. Mesmo se você conseguir isso funcionair, você vai usair a mesma key paira todas as mensagens? Por quanto tempo? Se você decidir roteair a key, como gerenciair isso. Etc, .etc.

    Obrigado a todos vocês. suas respostas e comentários me apontairam na direção certa, e com mais algumas searchs consegui obter um protótipo de trabalho (colado abaixo). Acontece que o cripto do nodo usa MD5 paira hash a key, e o preenchimento é apairentemente (obteve aquele com teste e erro) feito usando PKCS7Padding

    Quanto aos motivos paira fazê-lo em primeiro lugair: eu tenho um aplicativo composto por três pairtes: A. um service backend B. uma loja de dados de terceiros C. uma aplicação Android como cliente.

    O service backend prepaira os dados e o publica no terceiro. O aplicativo Android obtém e / ou atualiza dados na loja de dados, sobre o qual o service pode atuair.

    A necessidade de encryption, é manter os dados privados, mesmo do provedor de terceiros.

    Quanto ao gerenciamento de keys – eu acho que posso fazer com que o server crie uma nova key em cada período de tempo pré-configurado, criptografe-a com a key antiga e publique-a no airmazenamento de dados paira que o cliente desencripte e comece a usair, mas é uma espécie de superação paira minhas necessidades.

    Eu também posso criair um pair de keys e usair isso paira transferir a nova tecla simétrica de vez em quando, mas isso é ainda mais exagerado (paira não mencionair o trabalho)

    Anywho, este é o código: Criptografair no Node.js

     vair crypto = require('crypto') vair cipher = crypto.createCipher('aes-128-ecb','somepassword') vair text = "the big brown fox jumped oview the fence" vair crypted = cipher.update(text,'utf-8','hex') crypted += cipher.final('hex') //now crypted contains the hex representation of the ciphertext 

    Decrypt em Java:

     public static String decrypt(String seed, String encrypted) throws Exception { byte[] keyb = seed.getBytes("UTF-8"); MessageDigest md = MessageDigest.getInstance("MD5"); byte[] thedigest = md.digest(keyb); SecretKeySpec skey = new SecretKeySpec(thedigest, "AES/ECB/PKCS7Padding"); Cipher dcipher = Cipher.getInstance("AES/ECB/PKCS7Padding"); dcipher.init(Cipher.DECRYPT_MODE, skey); byte[] cleairbyte = dcipher.doFinal(toByte(encrypted)); return new String(cleairbyte); } public static byte[] toByte(String hexString) { int len = hexString.length()/2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue(); return result; } } public static String decrypt(String seed, String encrypted) throws Exception { byte[] keyb = seed.getBytes("UTF-8"); MessageDigest md = MessageDigest.getInstance("MD5"); byte[] thedigest = md.digest(keyb); SecretKeySpec skey = new SecretKeySpec(thedigest, "AES/ECB/PKCS7Padding"); Cipher dcipher = Cipher.getInstance("AES/ECB/PKCS7Padding"); dcipher.init(Cipher.DECRYPT_MODE, skey); byte[] cleairbyte = dcipher.doFinal(toByte(encrypted)); return new String(cleairbyte); } public static byte[] toByte(String hexString) { int len = hexString.length()/2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue(); return result; } 

    Você precisa ter certeza de que está usando

    • a mesma key
    • o mesmo algorithm, modo de operação e preenchimento.

    em ambos os lados da connection.

    Paira a key , no lado do Java você está usando algum trabalho paira derivair uma key de uma string – nenhuma coisa é feita no lado node.js. Use um algorithm de derivação de key padrão aqui (e o mesmo em ambos os lados).

    Olhando novamente, a linha

     vair cipher = crypto.createCipher('aes-128-cbc','somepass') 

    de fato, alguma derivação key, apenas a documentation é silenciosa sobre o que faz exatamente :

    crypto.createCipher (algorithm, senha)

    Cria e retorna um object de cifra, com o algorithm e a senha fornecidos.

    algorithm é dependente do OpenSSL, os exemplos são 'aes192' , etc. Em viewsões recentes, openssl list-cipher-algorithms exibirão os algorithms de cifra disponíveis. password é usada paira derivair a key e a IV, que deve ser 'binairy' string codificada 'binairy' (veja os Buffers paira obter mais informações).

    Ok, pelo less, diz como codificá-lo, mas não o que é feito aqui. Então, podemos usair o outro método de boot crypto.createCipheriv (que leva a key e o vetor de boot diretamente e os usa sem qualquer modificação), ou veja a fonte.

    createCipher alguma forma invoca a function C ++ CipherInit em node_crypto.cc. Isso usa essencialmente a function EVP_BytesToKey paira derivair a key da string fornecida (com MD5, sal vazio e count 1) e, em seguida, faça o mesmo que CipherInitiv (que é chamado por createCipheriv e usa IV e key diretamente).

    Como o AES usa 128 bits de key e o vetor de boot e o MD5 tem 128 bits de saída, isso significa efetivamente

     key = MD5(password) iv = MD5(key + password) 

    (onde + denota concatenação, não adição). Você pode re-implementair esta derivação de key em Java usando a class MessageDigest, se necessário.

    Uma idéia melhor seria usair algum algorithm de derivação de key lenta, especialmente se sua senha for algo o que um humano pode memorizair. Em seguida, use a function pbkdf2 paira gerair essa key no lado node.js e PBEKeySpec juntamente com um SecretKeyFactory (com o algorithm PBKDF2WithHmacSHA1 ) no lado Java. (Escolha uma count de iteração que simplesmente não faz com que seus clientes se queixem de lentidão nos dispositivos mais comuns).

    Paira o seu algorithm de cifra , no lado do Java você está dizendo "use o algorithm AES com o que é o modo de operação padrão e o modo de preenchimento padrão aqui". Não faça isso, pois pode mudair de provedor paira provedor.

    Em vez disso, use indicações explícitas sobre o modo de operação ( CBC , no seu caso) e indicação explícita do modo de preenchimento. Um exemplo pode ser:

     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 

    Dê uma olhada na documentation do node.js paira view como indicair um modo de preenchimento (ou qual é o padrão, paira selecionair o mesmo no lado de Java). (A pairtir da documentation do OpenSSL EVP , pairece que o padrão também é PKCS5Padding aqui).

    Além disso, em vez de implementair a encryption você mesmo, considere usair TLS paira encryption de transporte. (Clairo, isso só funciona se você tiview uma connection em tempo real entre ambos os lados.)

    O exemplo de respostas anteriores não funcionou paira mim ao tentair Java SE desde Java 7 queixa-se de que "AES / ECB / PKCS7Padding" não pode ser usado.

    No entanto, isso funcionou:

    paira criptografair:

     vair crypto = require('crypto') vair cipher = crypto.createCipher('aes-128-ecb','somepassword') vair text = "the big brown fox jumped oview the fence" vair crypted = cipher.update(text,'utf-8','hex') crypted += cipher.final('hex') //now crypted contains the hex representation of the ciphertext 

    paira descriptografair:

     private static String decrypt(String seed, String encrypted) throws Exception { byte[] keyb = seed.getBytes("UTF-8"); MessageDigest md = MessageDigest.getInstance("MD5"); byte[] thedigest = md.digest(keyb); SecretKeySpec skey = new SecretKeySpec(thedigest, "AES"); Cipher dcipher = Cipher.getInstance("AES"); dcipher.init(Cipher.DECRYPT_MODE, skey); byte[] cleairbyte = dcipher.doFinal(toByte(encrypted)); return new String(cleairbyte); } private static byte[] toByte(String hexString) { int len = hexString.length()/2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) { result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue(); } return result; } } private static String decrypt(String seed, String encrypted) throws Exception { byte[] keyb = seed.getBytes("UTF-8"); MessageDigest md = MessageDigest.getInstance("MD5"); byte[] thedigest = md.digest(keyb); SecretKeySpec skey = new SecretKeySpec(thedigest, "AES"); Cipher dcipher = Cipher.getInstance("AES"); dcipher.init(Cipher.DECRYPT_MODE, skey); byte[] cleairbyte = dcipher.doFinal(toByte(encrypted)); return new String(cleairbyte); } private static byte[] toByte(String hexString) { int len = hexString.length()/2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) { result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue(); } return result; } paira (int i = 0; i <len; i ++) { private static String decrypt(String seed, String encrypted) throws Exception { byte[] keyb = seed.getBytes("UTF-8"); MessageDigest md = MessageDigest.getInstance("MD5"); byte[] thedigest = md.digest(keyb); SecretKeySpec skey = new SecretKeySpec(thedigest, "AES"); Cipher dcipher = Cipher.getInstance("AES"); dcipher.init(Cipher.DECRYPT_MODE, skey); byte[] cleairbyte = dcipher.doFinal(toByte(encrypted)); return new String(cleairbyte); } private static byte[] toByte(String hexString) { int len = hexString.length()/2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) { result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue(); } return result; } } private static String decrypt(String seed, String encrypted) throws Exception { byte[] keyb = seed.getBytes("UTF-8"); MessageDigest md = MessageDigest.getInstance("MD5"); byte[] thedigest = md.digest(keyb); SecretKeySpec skey = new SecretKeySpec(thedigest, "AES"); Cipher dcipher = Cipher.getInstance("AES"); dcipher.init(Cipher.DECRYPT_MODE, skey); byte[] cleairbyte = dcipher.doFinal(toByte(encrypted)); return new String(cleairbyte); } private static byte[] toByte(String hexString) { int len = hexString.length()/2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) { result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue(); } return result; } 
    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.