O que eu preciso é criptografar a string que será exibida no código de barras 2D (PDF-417). Assim, quando alguém tiver uma idéia para digitalizar, nada ficará legível.
Outros requerimentos:
- não deve ser complicado
- não deve consistir em RSA, infraestrutura PKI, pares de chaves etc.
Deve ser simples o suficiente para se livrar das pessoas bisbilhoteiras e fácil de descriptografar para outras empresas interessadas em obter esses dados. Eles nos chamam, dizemos o padrão ou damos a eles uma chave simples que pode ser usada para descriptografia.
Provavelmente essas empresas poderiam usar tecnologias diferentes, por isso seria bom seguir algum padrão que não esteja vinculado a alguma plataforma ou tecnologia especial.
O que você sugere? Existe alguma classe Java fazendo encrypt()
e decrypt()
sem muita complicação na obtenção de altos padrões de segurança?
fonte
Respostas:
Prefácio
A seguir, descreverei o básico da criptografia simétrica segura e apontarei os erros comuns que vejo online quando as pessoas implementam criptografia por conta própria com a biblioteca Java padrão. Se você quiser pular todos os detalhes, vá para a nova biblioteca do Google. Importe isso para o seu projeto e use o modo AES-GCM para todas as suas criptografias e você estará seguro.
Agora, se você quiser aprender os detalhes básicos sobre como criptografar em java, continue lendo :)
Cifras de bloco
Primeiro, você precisa escolher uma chave simétrica Block Cipher. Uma cifra de bloco é uma função / programa de computador usada para criar pseudo-aleatoriedade. A pseudo-aleatoriedade é uma aleatoriedade falsa que nenhum computador que não seja um computador quântico seria capaz de distinguir a diferença entre ele e a aleatoriedade real. A Cifra de Bloco é como o bloco de construção da criptografia e, quando usado com diferentes modos ou esquemas, podemos criar criptografias.
Agora, sobre os algoritmos de codificação de bloco disponíveis hoje, certifique-se de NUNCA , repito NUNCA use DES , diria mesmo NUNCA use 3DES . O único Block Cipher que até o lançamento da NSA de Snowden foi capaz de verificar estar realmente o mais próximo possível do pseudo-aleatório possível é o AES 256 . Também existe AES 128; a diferença é que o AES 256 funciona em blocos de 256 bits, enquanto o AES 128 funciona em 128 blocos. Em suma, o AES 128 é considerado seguro, embora algumas fraquezas tenham sido descobertas, mas 256 é o mais sólido possível.
Curiosidade O DES foi quebrado pela NSA quando foi inicialmente fundado e, na verdade, manteve um segredo por alguns anos. Embora algumas pessoas ainda afirmem que o 3DES é seguro, existem muitos trabalhos de pesquisa que encontraram e analisaram pontos fracos no 3DES .
Modos de criptografia
A criptografia é criada quando você pega uma cifra de bloco e usa um esquema específico para que a aleatoriedade seja combinada com uma chave para criar algo que seja reversível, desde que você conheça a chave. Isso é chamado de modo de criptografia.
Aqui está um exemplo de um modo de criptografia e o modo mais simples conhecido como BCE, para que você possa entender visualmente o que está acontecendo:
Os modos de criptografia que você verá mais comumente online são os seguintes:
CTR do BCE, CBC, GCM
Existem outros modos fora dos listados e os pesquisadores estão sempre trabalhando em novos modos para melhorar os problemas existentes.
Agora vamos às implementações e ao que é seguro. NUNCA use o BCE, isso é ruim para ocultar dados repetidos, como mostra o famoso pinguim Linux .
Ao implementar em Java, observe que, se você usar o seguinte código, o modo ECB será definido por padrão:
... PERIGO, ESTA É UMA VULNERABILIDADE! e, infelizmente, isso é visto em todo o StackOverflow e on-line em tutoriais e exemplos.
Nonces e IVs
Em resposta à questão encontrada no modo BCE, também foram criados nomes conhecidos como IVs. A idéia é que geremos uma nova variável aleatória e a anexemos a toda criptografia, para que, quando você criptografar duas mensagens iguais, elas saiam diferentes. A beleza por trás disso é que um IV ou nonce é de conhecimento público. Isso significa que um invasor pode ter acesso a isso, mas desde que não possua sua chave, não poderá fazer nada com esse conhecimento.
Problemas comuns que verei é que as pessoas definirão o IV como um valor estático, como no mesmo valor fixo em seu código. e aqui está a armadilha para os IVs no momento em que você repete um, você realmente compromete toda a segurança de sua criptografia.
Gerando um IV aleatório
Nota: O SHA1 está quebrado, mas não consegui descobrir como implementar o SHA256 nesse caso de uso corretamente; portanto, se alguém quiser fazer uma rachadura e atualizá-lo, seria incrível! Além disso, os ataques SHA1 ainda não são convencionais, pois pode levar alguns anos em um grande cluster para quebrar. Confira os detalhes aqui.
Implementação de CTR
Não é necessário preenchimento para o modo CTR.
Implementação de CBC
Se você optar por implementar o Modo CBC, faça-o com PKCS7Padding da seguinte maneira:
Vulnerabilidade de CBC e CTR e por que você deve usar o GCM
Embora alguns outros modos, como CBC e CTR, sejam seguros, eles enfrentam o problema em que um invasor pode inverter os dados criptografados, alterando seu valor quando descriptografado. Então, digamos que você criptografa uma mensagem bancária imaginária "Sell 100", sua mensagem criptografada se parece com "eu23ng", o invasor muda um pouco para "eu53ng" e, de repente, quando descriptografa sua mensagem, lê-se como "Sell 900".
Para evitar isso, a maioria da internet usa o GCM, e toda vez que você vê HTTPS, provavelmente está usando o GCM. O GCM assina a mensagem criptografada com um hash e verifica se a mensagem não foi alterada usando esta assinatura.
Eu evitaria implementar o GCM devido à sua complexidade. É melhor usar a nova biblioteca do Google, Tink, porque aqui novamente, se você repetir acidentalmente um IV, estará comprometendo a chave no caso do GCM, que é a falha definitiva de segurança. Novos pesquisadores estão trabalhando para os modos de criptografia resistente à repetição IV, onde, mesmo se você repetir o IV, a chave não está em perigo, mas isso ainda está por vir.
Agora, se você deseja implementar o GCM, aqui está um link para uma boa implementação do GCM . No entanto, não posso garantir a segurança ou se está devidamente implementada, mas reduz a base. Observe também que no GCM não há preenchimento.
Chaves vs senhas
Outra observação muito importante é que, quando se trata de criptografia, uma chave e uma senha não são as mesmas coisas. Uma chave na criptografia precisa ter uma certa quantidade de entropia e aleatoriedade para ser considerada segura. É por isso que você precisa se certificar de usar as bibliotecas criptográficas adequadas para gerar a chave para você.
Então você realmente tem duas implementações que você pode fazer aqui, a primeira é usar o código encontrado neste encadeamento StackOverflow para geração de chave aleatória . Esta solução usa um gerador de números aleatórios seguro para criar uma chave do zero que você pode usar.
A outra opção menos segura é usar a entrada do usuário, como uma senha. O problema, como discutimos, é que a senha não tem entropia suficiente, portanto, teríamos que usar o PBKDF2 , um algoritmo que pega a senha e a fortalece. Aqui está uma implementação StackOverflow que eu gostei . No entanto, a biblioteca do Google Tink tem tudo isso embutido e você deve tirar proveito disso.
Desenvolvedores Android
Um ponto importante a ser destacado aqui é saber que seu código Android é reversível e, na maioria dos casos, a maioria dos códigos Java também. Isso significa que se você armazenar a senha em texto sem formatação no seu código. Um hacker pode recuperá-lo facilmente. Normalmente, para esse tipo de criptografia, você deseja usar a criptografia assimétrica e assim por diante. Isso está fora do escopo deste post, por isso vou evitar mergulhar nele.
Uma leitura interessante de 2013 : salienta que 88% das implementações de criptografia no Android foram feitas de maneira inadequada.
Pensamentos finais
Mais uma vez, sugiro evitar a implementação da biblioteca java para criptografia diretamente e usar o Google Tink . Isso poupará a dor de cabeça, pois eles realmente fizeram um bom trabalho ao implementar todos os algoritmos corretamente. E mesmo assim, verifique as questões levantadas no github Tink, as vulnerabilidades aparecem aqui e ali.
Se você tiver alguma dúvida ou feedback, sinta-se à vontade para comentar! A segurança está sempre mudando e você precisa fazer o possível para acompanhá-la :)
fonte
getInstanceStrong()
método deCipher
é preferível ao longo SHA1PRNGEu recomendaria usar algum código simétrico padrão amplamente disponível como DES , 3DES ou AES . Embora esse não seja o algoritmo mais seguro, existem muitas implementações e você só precisa fornecer a chave para qualquer pessoa que decodifique as informações no código de barras. javax.crypto.Cipher é com o que você deseja trabalhar aqui.
Vamos supor que os bytes a serem criptografados estejam em
Em seguida, você precisará dos bytes do vetor de chave e inicialização
Agora você pode inicializar a cifra para o algoritmo selecionado:
A criptografia seria assim:
E descriptografia como esta:
fonte
DESede
algoritmo? Como essa é uma pergunta popular (e resposta), seria uma pena incentivar as pessoas a usar o DES, uma vez que a cifra é tão fraca para os padrões atuais.Estou usando o Base64Encoder / Decoder da Sun, que pode ser encontrado no JRE da Sun, para evitar outro JAR na lib. Isso é perigoso do ponto de usar o OpenJDK ou o JRE de outra pessoa. Além disso, existe outro motivo pelo qual eu deveria considerar o uso do Apache commons lib com o Encoder / Decoder?
fonte
obrigado ive fez esta classe usando o seu código talvez alguém ache userfull
criptografador de objetos
fonte
Atualização em 12-DEC-2019
Ao contrário de outros modos, como o CBC, o modo GCM não exige que o IV seja imprevisível. O único requisito é que o IV tenha que ser exclusivo para cada chamada com uma determinada chave. Se ele se repetir uma vez para uma determinada chave, a segurança pode ser comprometida. Uma maneira fácil de conseguir isso é usar um IV aleatório de um forte gerador de números pseudo-aleatórios, como mostrado abaixo.
O uso de uma sequência ou registro de data e hora como IV também é possível, mas pode não ser tão trivial quanto possível. Por exemplo, se o sistema não acompanhar corretamente as seqüências já usadas como IV em um armazenamento persistente, uma chamada poderá repetir um IV após a reinicialização do sistema. Da mesma forma, não há relógio perfeito. O relógio do computador reajusta etc.
Além disso, a chave deve ser girada após cada 2 ^ 32 invocações. Para mais detalhes sobre o requisito IV, consulte esta resposta e as recomendações do NIST .
Este é o código de criptografia e descriptografia que acabei de escrever no Java 8, considerando os seguintes pontos. Espero que alguém ache isso útil:
Algoritmo de criptografia : O AES da cifra de bloco com chave de 256 bits é considerado suficientemente seguro. Para criptografar uma mensagem completa, um modo precisa ser selecionado. A criptografia autenticada (que fornece confidencialidade e integridade) é recomendada. GCM, CCM e EAX são os modos de criptografia autenticada mais comumente usados. O GCM é geralmente preferido e apresenta bom desempenho nas arquiteturas Intel, que fornecem instruções dedicadas para o GCM. Todos esses três modos são baseados em CTR (contador) e, portanto, não precisam de preenchimento. Como resultado, eles não são vulneráveis a ataques relacionados ao preenchimento
Um vetor de inicialização (IV) é necessário para o GCM. O IV não é um segredo. O único requisito é que deve ser aleatório ou imprevisível. Em Java, a
SecuredRandom
classe pretende produzir números pseudo-aleatórios criptograficamente fortes. O algoritmo de geração de números pseudo-aleatórios pode ser especificado nogetInstance()
método No entanto, desde o Java 8, a maneira recomendada é usar ogetInstanceStrong()
método que usará o algoritmo mais forte configurado e fornecido peloProvider
O NIST recomenda 96 bits IV para o GCM para promover a interoperabilidade, eficiência e simplicidade do design
Para garantir segurança adicional, na implementação a seguir
SecureRandom
é re-propagada após a produção a cada 2 ^ 16 bytes de geração de bytes pseudo-aleatóriosO destinatário precisa conhecer o IV para poder descriptografar o texto cifrado. Portanto, o IV precisa ser transferido junto com o texto cifrado. Algumas implementações enviam o IV como AD (Dados Associados), o que significa que a marca de autenticação será calculada no texto cifrado e no IV. No entanto, isso não é necessário. O IV pode ser simplesmente pendente com o texto cifrado, porque se o IV for alterado durante a transmissão devido a um ataque deliberado ou erro no sistema de rede / arquivo, a validação da tag de autenticação falhará de qualquer maneira
As strings não devem ser usadas para conter a mensagem de texto não criptografado ou a tecla, pois as strings são imutáveis e, portanto, não podemos eliminá-las após o uso. Essas seqüências de caracteres não claras permanecem na memória e podem aparecer em um despejo de pilha. Pelo mesmo motivo, o cliente que chama esses métodos de criptografia ou descriptografia deve limpar todas as variáveis ou matrizes que contêm a mensagem ou a chave depois que elas não forem mais necessárias.
Nenhum provedor é codificado no código seguindo as recomendações gerais
Finalmente, para transmissão pela rede ou armazenamento, a chave ou o texto cifrado deve ser codificado usando a codificação Base64. Os detalhes do Base64 podem ser encontrados aqui . A abordagem Java 8 deve ser seguida
As matrizes de bytes podem ser limpas usando:
No entanto, no Java 8, não há uma maneira fácil de limpar
SecretKeyspec
e,SecretKey
como as implementações dessas duas interfaces não parecem ter implementado o métododestroy()
da interfaceDestroyable
. No código a seguir, um método separado é gravado para limparSecretKeySpec
eSecretKey
usar a reflexão.A chave deve ser gerada usando uma das duas abordagens mencionadas abaixo.
Observe que as chaves são segredos, como senhas, mas, diferentemente das senhas destinadas ao uso humano, as chaves devem ser usadas por algoritmos criptográficos e, portanto, devem ser geradas usando apenas a maneira acima.
A chave de criptografia pode ser gerada principalmente de duas maneiras:
Sem nenhuma senha
Com senha
Atualização baseada em comentários
Conforme apontado por @MaartenBodewes, minha resposta não lidou com nada
String
conforme exigido pela pergunta. Portanto, farei uma tentativa de preencher essa lacuna para o caso de alguém topar com essa resposta e deixar de pensar em como lidarString
.Conforme indicado anteriormente na resposta, manipular informações confidenciais em a
String
geralmente não é uma boa ideia porqueString
é imutável e, portanto, não podemos eliminá-las após o uso. E como sabemos, mesmo quando umString
não tem uma referência forte, o coletor de lixo não corre imediatamente para removê-lo da pilha. Portanto, eleString
permanece na memória por uma janela desconhecida, mesmo que não seja acessível ao programa. O problema disso é que um despejo de pilha durante esse período revelaria as informações confidenciais. Portanto, é sempre melhor manipular todas as informações confidenciais em uma matriz de bytes ou em uma matriz de caracteres e, em seguida, preencher a matriz com 0s quando o objetivo for atendido.No entanto, com todo esse conhecimento, se ainda acabarmos em uma situação em que as informações confidenciais a serem criptografadas estão em a
String
, primeiro precisamos convertê-las em uma matriz de bytes e invocar as funçõesencrypt
edecrypt
apresentadas acima. (A outra chave de entrada pode ser gerada usando o snippet de código fornecido acima).A
String
pode ser convertido em bytes da seguinte maneira:A partir do Java 8,
String
é armazenado internamente em heap comUTF-16
codificação. No entanto, usamosUTF-8
aqui, pois geralmente ocupa menos espaço do queUTF-16
, especialmente para caracteres ASCII.Da mesma forma, a matriz de bytes criptografados também pode ser convertida em uma String, como abaixo:
fonte
String
usando as funções criadas acima seria trivial. No entanto, depois de ler seu comentário, entendo que isso pode não ser óbvio. Certamente vou editar para adicionar esses detalhes.Que tal agora:
Funciona bem para mim e é bastante compacto.
fonte
input.length <= secret.length
detém e nãosecret
é reutilizado, isso é seguro e chamado deone-time-pad
. Nos casosinput.length > secret.length
disso, é uma variante da cifra de Vigenère e considerada muito fraca.Você pode usar o Jasypt
Com o Jasypt, criptografar e verificar uma senha pode ser tão simples quanto ...
Criptografia:
Descriptografia:
Gradle:
Recursos:
fonte
Jasypt
fornece? Não consigo descobrir no site deles. É indistinguível sob ataques de texto simples escolhido? Integridade? Confidencialidade?Aqui está minha implementação do meta64.com como Spring Singleton. Se você deseja criar uma instância de ciper para cada chamada que funcione também e remover as chamadas 'sincronizadas', mas cuidado com o 'cipher' não é seguro para threads.
fonte
Aqui, uma solução simples, com apenas
java.*
ejavax.crypto.*
dependências para criptografia de bytes, fornecendo confidencialidade e integridade . Deve ser indistinguível sob um ataque de texto simples escolhido para mensagens curtas na ordem de kilobytes.Ele usa
AES
noGCM
modo sem preenchimento, uma chave de 128 bits é derivadaPBKDF2
com muitas iterações e um sal estático da senha fornecida. Isso garante que as senhas de força bruta sejam difíceis e distribua a entropia por toda a chave.Um vetor de inicialização aleatória (IV) é gerado e será anexado ao texto cifrado. Além disso, o byte estático
0x01
é acrescentado como o primeiro byte como uma 'versão'.A mensagem inteira entra no código de autenticação de mensagem (MAC) gerado por
AES/GCM
.Aqui vai, zero classe de criptografia de dependências externas, fornecendo confidencialidade e integridade :
Aqui está o projeto inteiro com uma bela CLI: https://github.com/trichner/tcrypt
Editar: agora com o apropriado
encryptString
edecryptString
fonte
encryptString
edecryptString
:)Eu consideraria usar algo como https://www.bouncycastle.org/ É uma biblioteca pré-construída que permite criptografar o que você quiser com um número de cifras diferentes. Entendo que você só quer se proteger da espionagem, mas se realmente deseja proteger as informações, o uso do Base64 não o protegerá.
fonte
Aqui estão alguns links para você ler o que o Java suporta
Criptografar / descriptografar um fluxo de dados.
JCERefGuide
Exemplos de criptografia Java
fonte
Como muitos dos caras já disseram, você deve usar um codificador padrão que seja excessivamente usado como DES ou AES.
Um exemplo simples de como você pode criptografar e descriptografar uma string em java usando o AES .
fonte
Aqui está uma solução de copiar / colar. Também recomendo ler e votar na resposta do @ Konstantino, mesmo que ela não forneça nenhum código. O vetor de inicialização (IV) é como um sal - não precisa ser mantido em segredo. Eu sou novo no GCM e, aparentemente, o AAD é opcional e usado apenas em determinadas circunstâncias. Defina a chave na variável de ambiente
SECRET_KEY_BASE
. Use algo como o KeePass para gerar uma senha de 32 caracteres. Esta solução foi modelada após a minha solução Ruby.Aqui está um exemplo:
fonte
Você pode considerar uma ferramenta automatizada para gerar o código de criptografia / descriptografia, por exemplo. https://www.stringencrypt.com/java-encryption/
Ele pode gerar diferentes códigos de criptografia e descriptografia a cada vez para a criptografia de cadeia ou arquivo.
É bastante útil quando se trata de criptografia rápida de cadeias sem usar RSA, AES etc.
Resultados da amostra:
Usamos o tempo todo em nossa empresa.
fonte
fonte
fonte