O que há de errado com o exemplo a seguir?
O problema é que a primeira parte da string descriptografada não faz sentido. Porém, o resto está bem, eu entendo ...
Result: `£eB6O�geS��i are you? Have a nice day.
@Test
public void testEncrypt() {
try {
String s = "Hello there. How are you? Have a nice day.";
// Generate key
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
SecretKey aesKey = kgen.generateKey();
// Encrypt cipher
Cipher encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
encryptCipher.init(Cipher.ENCRYPT_MODE, aesKey);
// Encrypt
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, encryptCipher);
cipherOutputStream.write(s.getBytes());
cipherOutputStream.flush();
cipherOutputStream.close();
byte[] encryptedBytes = outputStream.toByteArray();
// Decrypt cipher
Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivParameterSpec = new IvParameterSpec(aesKey.getEncoded());
decryptCipher.init(Cipher.DECRYPT_MODE, aesKey, ivParameterSpec);
// Decrypt
outputStream = new ByteArrayOutputStream();
ByteArrayInputStream inStream = new ByteArrayInputStream(encryptedBytes);
CipherInputStream cipherInputStream = new CipherInputStream(inStream, decryptCipher);
byte[] buf = new byte[1024];
int bytesRead;
while ((bytesRead = cipherInputStream.read(buf)) >= 0) {
outputStream.write(buf, 0, bytesRead);
}
System.out.println("Result: " + new String(outputStream.toByteArray()));
}
catch (Exception ex) {
ex.printStackTrace();
}
}
java
encryption
aes
TedTrippin
fonte
fonte
Respostas:
Muitas pessoas, inclusive eu, enfrentam muitos problemas para fazer este trabalho devido à falta de algumas informações, como esquecer de converter para Base64, vetores de inicialização, conjunto de caracteres, etc. Então pensei em fazer um código totalmente funcional.
Espero que seja útil para todos vocês: Para compilar, você precisa de um jar adicional do Apache Commons Codec, que está disponível aqui: http://commons.apache.org/proper/commons-codec/download_codec.cgi
fonte
System.out.println("encrypted string:" + DatatypeConverter.printBase64Binary(encrypted));
byte[] original = cipher.doFinal(DatatypeConverter.parseBase64Binary(encrypted));
SecureRandom
Aqui está uma solução sem
Apache Commons Codec
'sBase64
:Exemplo de uso:
Impressões:
fonte
encrypt(String)
e nãoencrypt(byte[] )
? A criptografia (descriptografia também) é um processo baseado em bytes (AES é assim mesmo). A criptografia recebe bytes como entrada e emite bytes, assim como a descriptografia (caso em questão: oCipher
objeto sim). Agora, um caso de uso particular pode ser ter bytes criptografados vindos de uma String, ou ser enviado como uma String (anexo MIME base64 para um Mail ...), mas isso é um problema de bytes de codificação, para os quais existem centenas de soluções totalmente alheias a AES / criptografia.Strings
porque é basicamente com isso que trabalho 95% do tempo e você acaba convertendo de qualquer maneira.Parece-me que você não está lidando corretamente com o seu vetor de inicialização (IV). Já se passou muito tempo desde a última vez que li sobre AES, IVs e encadeamento de blocos, mas sua linha
não parece estar bem. No caso do AES, você pode pensar no vetor de inicialização como o "estado inicial" de uma instância de cifra, e esse estado é um bit de informação que você não pode obter de sua chave, mas do cálculo real da cifra de criptografia. (Pode-se argumentar que se o IV pudesse ser extraído da chave, não teria utilidade, pois a chave já foi fornecida à instância da cifra durante sua fase de inicialização).
Portanto, você deve obter o IV como um byte [] da instância de cifra no final de sua criptografia
e você deve inicializar seu
Cipher
inDECRYPT_MODE
com este byte []:Então, sua descriptografia deve estar OK. Espero que isto ajude.
fonte
O IV que você está usando para descriptografar está incorreto. Substitua este código
Com este código
E isso deve resolver seu problema.
Abaixo inclui um exemplo de uma classe AES simples em Java. Não recomendo o uso dessa classe em ambientes de produção, pois ela pode não atender a todas as necessidades específicas de seu aplicativo.
Observe que AES não tem nada a ver com codificação, por isso optei por tratá-lo separadamente e sem a necessidade de nenhuma biblioteca de terceiros.
fonte
"/NoPadding"
. CTR é um modo que transforma AES em uma cifra de fluxo, e uma cifra de fluxo opera em bytes em vez de blocos.Nesta resposta, optei por abordar o tema principal "Exemplo de criptografia / descriptografia simples de Java AES" e não a questão de depuração específica, porque acho que isso irá beneficiar a maioria dos leitores.
Este é um resumo simples da postagem do meu blog sobre criptografia AES em Java portanto, recomendo a leitura antes de implementar qualquer coisa. No entanto, ainda fornecerei um exemplo simples para usar e darei algumas dicas sobre o que observar.
Neste exemplo, vou escolher usar criptografia autenticada com modo Galois / Contador ou modo GCM . A razão é que na maioria dos casos você deseja integridade e autenticidade combinadas com confidencialidade (leia mais no blog ).
Tutorial de criptografia / descriptografia AES-GCM
Aqui estão as etapas necessárias para criptografar / descriptografar com AES-GCM com a Java Cryptography Architecture (JCA) . Não misture com outros exemplos , pois diferenças sutis podem tornar seu código totalmente inseguro.
1. Criar chave
Como depende do seu caso de uso, assumirei o caso mais simples: uma chave secreta aleatória.
Importante:
SecureRandom
2. Crie o vetor de inicialização
Um vetor de inicialização (IV) é usado para que a mesma chave secreta crie diferentes textos cifrados .
Importante:
SecureRandom
3. Criptografar com IV e Chave
Importante:
CipherInputStream
ao criptografar grandes blocos de dadoscipher.updateAAD(associatedData);
Mais aqui.3. Serializar para mensagem única
Basta anexar IV e o texto cifrado. Como afirmado acima, o IV não precisa ser segredo.
Opcionalmente, codifique com Base64 se precisar de uma representação de string. Use a implementação integrada do Android ou do Java 8 (não use o Apache Commons Codec - é uma implementação horrível). A codificação é usada para "converter" matrizes de bytes em representação de string para torná-las ASCII seguras, por exemplo:
4. Prepare a descriptografia: desserialize
Se você codificou a mensagem, primeiro decodifique-a para a matriz de bytes:
Importante:
5. Descriptografar
Inicialize a cifra e defina os mesmos parâmetros da criptografia:
Importante:
cipher.updateAAD(associatedData);
se você os adicionou durante a criptografia.Um trecho de código funcional pode ser encontrado nesta essência.
Observe que as implementações mais recentes do Android (SDK 21+) e Java (7 +) devem ter AES-GCM. Versões mais antigas podem não ter. Eu ainda escolho este modo, pois é mais fácil de implementar além de ser mais eficiente em comparação com o modo semelhante de Encrypt-then-Mac (com por exemplo AES-CBC + HMAC ). Veja este artigo sobre como implementar AES-CBC com HMAC .
fonte
this is true for CBC mode but not for GCM
você quer dizer a parte inteira, ou apenas não precisa ser realmente imprevisível?Versão executável do Editor Online: -
fonte
Muitas vezes é uma boa ideia confiar na solução fornecida pela biblioteca padrão:
Isso imprime "Texto a codificar".
A solução é baseada no Java Cryptography Architecture Reference Guide e https://stackoverflow.com/a/20591539/146745 resposta.
fonte
Esta é uma melhoria em relação à resposta aceita.
Alterar:
(1) Usando IV aleatório e anexá-lo ao texto criptografado
(2) Usando SHA-256 para gerar uma chave a partir de uma senha
(3) Sem dependência do Apache Commons
fonte
Outra solução usando java.util.Base64 com Spring Boot
Classe Encryptor
Classe EncryptorController
application.properties
Exemplo
http: // localhost: 8082 / cipher / encrypt / jmendoza
2h41HH8Shzc4BRU3hVDOXA ==
http: // localhost: 8082 / cipher / decrypt / 2h41HH8Shzc4BRU3hVDOXA ==
jmendoza
fonte
Versão otimizada da resposta aceita.
sem libs de terceiros
inclui IV na mensagem criptografada (pode ser público)
a senha pode ter qualquer comprimento
Código:
Uso:
Saída de exemplo:
fonte
e.printStackTrace()
no chamado código otimizado.