Preciso implementar a criptografia AES de 256 bits, mas todos os exemplos que encontrei on-line usam um "KeyGenerator" para gerar uma chave de 256 bits, mas gostaria de usar minha própria senha. Como posso criar minha própria chave? Eu tentei preenchê-lo para 256 bits, mas, em seguida, recebo um erro dizendo que a chave é muito longa. Eu tenho o patch de jurisdição ilimitado instalado, então esse não é o problema :)
Ou seja. O KeyGenerator se parece com isso ...
// Get the KeyGenerator
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); // 192 and 256 bits may not be available
// Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
EDITAR
Na verdade, eu estava preenchendo a senha com 256 bytes, não com bits, o que é muito longo. A seguir, alguns códigos que estou usando agora que tenho mais experiência com isso.
byte[] key = null; // TODO
byte[] input = null; // TODO
byte[] output = null;
SecretKeySpec keySpec = null;
keySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
output = cipher.doFinal(input)
Os bits "TODO" que você precisa fazer :-)
java
encryption
cryptography
passwords
aes
Nippysaurus
fonte
fonte
Respostas:
Compartilhe os
password
(achar[]
) esalt
(a -byte[]
8 bytes selecionados por umSecureRandom
faz um bom sal - que não precisa ser mantido em segredo) com o destinatário fora da banda. Em seguida, para obter uma boa chave dessas informações:Os números mágicos (que podem ser definidos como constantes em algum lugar) 65536 e 256 são a contagem de iterações de derivação de chave e o tamanho da chave, respectivamente.
A função de derivação de chave é iterada para exigir um esforço computacional significativo e impede que os invasores tentem rapidamente muitas senhas diferentes. A contagem de iterações pode ser alterada dependendo dos recursos de computação disponíveis.
O tamanho da chave pode ser reduzido para 128 bits, o que ainda é considerado criptografia "forte", mas não oferece grande margem de segurança se forem descobertos ataques que enfraquecem o AES.
Usado com um modo de encadeamento de blocos adequado, a mesma chave derivada pode ser usada para criptografar muitas mensagens. No Cipher Block Chaining (CBC) , um vetor de inicialização aleatória (IV) é gerado para cada mensagem, produzindo texto cifrado diferente, mesmo que o texto sem formatação seja idêntico. O CBC pode não ser o modo mais seguro disponível para você (consulte AEAD abaixo); existem muitos outros modos com diferentes propriedades de segurança, mas todos eles usam uma entrada aleatória semelhante. De qualquer forma, as saídas de cada operação de criptografia são o texto cifrado e o vetor de inicialização:
Armazene o
ciphertext
e oiv
. Na descriptografia, oSecretKey
é regenerado exatamente da mesma maneira, usando a senha com os mesmos parâmetros de sal e iteração. Inicialize a cifra com essa chave e o vetor de inicialização armazenado com a mensagem:O Java 7 incluiu suporte à API para modos de cifra AEAD , e o provedor "SunJCE" incluído nas distribuições OpenJDK e Oracle implementa estes a partir do Java 8. Um desses modos é altamente recomendado no lugar do CBC; protegerá a integridade dos dados, bem como a sua privacidade.
A
java.security.InvalidKeyException
com a mensagem "Tamanho da chave ilegal ou parâmetros padrão" significa que a força da criptografia é limitada; os arquivos de política de jurisdição de força ilimitada não estão no local correto. Em um JDK, eles devem ser colocados em${jdk}/jre/lib/security
Com base na descrição do problema, parece que os arquivos de políticas não foram instalados corretamente. Os sistemas podem facilmente ter vários tempos de execução Java; verifique duas vezes para garantir que o local correto esteja sendo usado.
fonte
PBEwith<prf>and<encryption>
algoritmos; por exemplo, o SunJCE não fornece e PBE para AES. Segundo, ativar o jasypt não é objetivo. Um pacote que pretende oferecer segurança sem exigir a compreensão dos princípios subjacentes parece perigoso à primeira vista.tmp.getEncoded()
como hash. Você também deve armazenar assalt
iterações (65536 neste exemplo) para poder recalcular o hash quando alguém tentar se autenticar. Nesse caso, gere o sal com um gerador de números aleatórios criptográficos sempre que a senha for alterada.Considere o uso do Spring Security Crypto Module
Ele fornece uma abstração simples para criptografia e parece corresponder ao necessário aqui,
Um exame das partes internas revela uma estrutura semelhante à resposta de erickson .
Conforme observado na pergunta, isso também requer a Política de Jurisdição de Força Ilimitada da Java Cryptography Extension (JCE) (caso contrário, você encontrará
InvalidKeyException: Illegal Key Size
). É possível fazer o download para Java 6 , Java 7 e Java 8 .Exemplo de uso
E amostra de saída,
fonte
NULL_IV_GENERATOR
usado pelo utilitário Spring não é seguro. Se o aplicativo não fornecer um IV, deixe que o provedor o escolha e consulte-o após a inicialização.Depois de ler as sugestões de erickson e recolher o que pude de algumas outras postagens e deste exemplo aqui , tentei atualizar o código de Doug com as alterações recomendadas. Sinta-se livre para editar para torná-lo melhor.
Algumas anotações: isso usa uma chave de criptografia de 128 bits - o java aparentemente não executa criptografia de 256 bits imediatamente. A implementação do 256 requer a instalação de alguns arquivos extras no diretório de instalação do java.
Além disso, eu não sou uma pessoa de criptografia. Fique atento.
fonte
printStackTrace()
CipherInputStream
eCipherOutputStream
não é um grande problema. Baralhar todas as exceções sob a tabela é um problema. O fato de que o sal se tornou repentinamente um campo e que o IV é necessário é um problema. O fato de não seguir as convenções de codificação Java é um problema. E o fato de que isso só funciona em arquivos enquanto não foi solicitado é um problema. E que o resto do código é basicamente uma cópia também não ajuda. Mas talvez eu o ajuste para torná-lo melhor, como sugerido ...É fácil gerar sua própria chave a partir de uma matriz de bytes:
Mas criar uma chave de 256 bits não é suficiente. Se o gerador de chaves não puder gerar chaves de 256 bits para você,
Cipher
provavelmente a classe também não suporta o AES de 256 bits. Você diz que possui o patch de jurisdição ilimitado instalado, portanto a cifra AES-256 deve ser suportada (mas as chaves de 256 bits também devem ser, portanto, isso pode ser um problema de configuração).Uma solução alternativa para a falta de suporte ao AES-256 é usar algumas implementações disponíveis gratuitamente do AES-256 e usá-lo como um provedor personalizado. Isso envolve criar sua própria
Provider
subclasse e usá-la comCipher.getInstance(String, Provider)
. Mas isso pode ser um processo envolvido.fonte
Cipher
, não no próprio provedor. Você pode usar o AES-256 no Java 8 e inferior, mas precisa usar uma API proprietária. Ou um tempo de execução que não impõe restrições ao tamanho da chave, é claro.O que eu fiz no passado foi fazer a hash da chave por meio de algo como SHA256 e extrair os bytes do hash para o byte da chave [].
Depois de ter seu byte [], você pode simplesmente:
fonte
Cipher aes256 = Cipher.getInstance("AES/OFB/NoPadding"); MessageDigest keyDigest = MessageDigest.getInstance("SHA-256"); byte[] keyHash = keyDigest.digest(secret.getBytes("UTF-8")); SecretKeySpec key = new SecretKeySpec(keyHash, "AES"); aes256.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(initializationVector));
Também estou fazendo o mesmo como sugerido na sua resposta, mas ainda assim acabo com este java.security.InvalidKeyException: tamanho de chave ilegal O download do arquivo de políticas do JCE é obrigatório?Adicionando às edições do @ Wufoo, a versão a seguir usa InputStreams em vez de arquivos para facilitar o trabalho com uma variedade de arquivos. Ele também armazena o IV e o Salt no início do arquivo, fazendo com que apenas a senha precise ser rastreada. Como o IV e o Sal não precisam ser secretos, isso facilita a vida.
fonte
(Talvez útil para outras pessoas com um requisito semelhante)
Eu tinha um requisito semelhante para usar
AES-256-CBC
criptografar e descriptografar em Java.Para alcançar (ou especificar) a criptografia / descriptografia de 256 bytes, a
Java Cryptography Extension (JCE)
política deve ser definida como"Unlimited"
Pode ser definido no
java.security
arquivo em$JAVA_HOME/jre/lib/security
(para JDK) ou$JAVA_HOME/lib/security
(para JRE)crypto.policy=unlimited
Ou no código como
O Java 9 e versões posteriores têm isso ativado por padrão.
fonte
Considere usar o Encryptor4j, do qual sou o autor.
Primeiro, verifique se os arquivos da Política de jurisdição de força ilimitada estão instalados antes de prosseguir para poder usar as chaves AES de 256 bits.
Em seguida, faça o seguinte:
Agora você pode usar o criptografador para criptografar sua mensagem. Você também pode executar a criptografia de streaming, se desejar. Ele gera e anexa automaticamente um IV seguro para sua conveniência.
Se for um arquivo que você deseja compactar, dê uma olhada nesta resposta Criptografando um arquivo grande com o AES usando JAVA para uma abordagem ainda mais simples.
fonte
Use esta classe para criptografia. Funciona.
E estes são ivBytes e uma chave aleatória;
fonte