如何在 Java 中加密字符串 [英] How to encrypt String in Java

查看:26
本文介绍了如何在 Java 中加密字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要的是对将显示在二维条码 (PDF-417) 中的字符串进行加密,这样当有人想扫描它时,它将无法读取.

其他要求:

  • 不应该复杂
  • 它不应包含 RSA、PKI 基础设施、密钥对等.

它必须足够简单以摆脱四处窥探的人,并且易于解密其他有兴趣获取该数据的公司.他们打电话给我们,我们告诉他们标准或给他们一些简单的密钥,然后可以用于解密.

可能这些公司可以使用不同的技术,因此最好坚持一些与某些特殊平台或技术无关的标准.

你有什么建议?是否有一些 Java 类在执行 encrypt() &decrypt() 在实现高安全标准方面没有太多复杂性?

解决方案

这是通过 Google 和安全显示的第一页所有实现中的漏洞让我畏缩,所以我发布此信息以添加有关其他人的加密信息距原始帖子 7 年.我拥有硕士学位计算机工程,花了很多时间学习和学习密码学,所以我花两分钱让互联网成为一个安全的地方.

另外,请注意对于给定的许多实现可能是安全的情况,但是为什么要使用这些并且可能会意外地做出错误?使用您可用的最强大的工具,除非您有不去的具体原因.总的来说,我强烈建议使用图书馆和如果可以,请远离细节.

更新 4/5/18: 我重写了一些部分以使它们更易于理解并更改了来自

您在网上最常看到的加密模式如下:

ECB CTR、CBC、GCM

在所列模式之外还存在其他模式,研究人员一直致力于开发新模式以改善现有问题.

现在让我们继续讨论实现以及什么是安全的.从不使用 ECB 这在隐藏重复数据方面很糟糕,正如著名的

在Java中实现时注意,如果使用如下代码,默认设置ECB模式:

Cipher cipher = Cipher.getInstance("AES");

...危险,这是一个漏洞!不幸的是,这在 StackOverflow 和在线教程和示例中随处可见.

随机数和 IV

为了解决 ECB 模式中发现的问题,我们创建了也称为 IV 的通知.这个想法是我们生成一个新的随机变量并将其附加到每个加密中,这样当您加密两个相同的消息时,它们就会不同.这背后的美妙之处在于 IV 或随机数是公共知识.这意味着攻击者可以访问此信息,但只要他们没有您的密钥,他们就无法利用这些信息做任何事情.

我会看到的常见问题是人们会将 IV 设置为静态值,就像在他们的代码中的固定值一样.当您重复一次时,这就是 IV 的陷阱,您实际上损害了加密的整个安全性.

生成随机 IV

SecureRandom randomSecureRandom = SecureRandom.getInstance("SHA1PRNG");字节[] iv = 新字节[密码.getBlockSize()];randomSecureRandom.nextBytes(iv);IvParameterSpec ivParams = 新的 IvParameterSpec(iv);

注意: SHA1 已损坏,但我找不到如何将 SHA256 正确实施到此用例中,因此,如果有人想对此进行破解并进行更新,那就太棒了!此外,SHA1 攻击仍然是非常规的,因为在一个巨大的集群上可能需要几年时间才能破解.在此处查看详细信息.

点击率实施

点击率模式不需要填充.

 Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");

CBC 实施

如果您选择实现 CBC 模式,请使用 PKCS7Padding 执行以下操作:

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

CBC 和 CTR 漏洞以及为什么应该使用 GCM

尽管其他一些模式(例如 CBC 和 CTR)是安全的,但它们会遇到攻击者可以翻转加密数据、在解密时更改其值的问题.因此,假设您加密了一条假想的银行消息Sell 100",您的加密消息看起来像这样eu23ng",攻击者将一位更改为eu53ng",然后在解密您的消息时,突然读到Sell 900".

为了避免这种情况,大多数互联网使用 GCM,并且每次您看到 HTTPS 时,他们可能都在使用 GCM.GCM 使用散列对加密消息进行签名,并使用此签名检查以验证消息是否未更改.

我会避免实施 GCM,因为它很复杂.你最好使用 Google 的新库 Tink,因为如果你不小心重复了一个 IV,你就会损害GCM 案例中的关键,这是最终的安全漏洞.新的研究人员正在努力开发抗 IV 重复加密模式,即使您重复 IV,密钥也不会处于危险之中,但这尚未成为主流.

现在,如果您确实想实施 GCM,这里有一个链接到一个不错的 GCM 实施.但是,我无法确保安全性,或者它是否正确实施,但它得到了基础.还要注意 GCM 没有填充.

Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

密钥与密码

另一个非常重要的注意事项是,在加密方面,密钥和密码不是一回事.密码学中的密钥需要具有一定的熵和随机性才能被认为是安全的.这就是为什么您需要确保使用正确的加密库为您生成密钥.

所以你真的有两个实现你可以在这里做,第一个是使用 这个用于随机密钥生成的 StackOverflow 线程.此解决方案使用安全的随机数生成器从头开始创建您可以使用的密钥.

另一个不太安全的选项是使用用户输入,例如密码.我们讨论的问题是密码没有足够的熵,所以我们必须使用 PBKDF2,一种获取密码并对其进行强化的算法.这是一个我喜欢的 StackOverflow 实现.但是,Google Tink 库内置了所有这些功能,您应该充分利用它.

Android 开发者

这里要指出的一个重要点是知道您的 android 代码是可反向工程的,并且大多数情况下大多数 java 代码也是如此.这意味着如果您在代码中以纯文本形式存储密码.黑客可以轻松地检索它.通常,对于这些类型的加密,您希望使用非对称加密等.这超出了本文的范围,因此我将避免深入探讨.

2013 年有趣的阅读:指出 88%Android 中的 Crypto 实现不正确.

最后的想法

我再次建议避免直接为加密实现 Java 库并使用 Google Tink,它将为您省去头疼的麻烦,因为他们在正确实施所有算法方面确实做得很好.即便如此,请确保您检查 Tink github 上提出的问题,漏洞无处不在.

如果您有任何问题或反馈,请随时发表评论!安全性总是在变化,您需要尽最大努力跟上它:)

What I need is to encrypt string which will show up in 2D barcode(PDF-417) so when someone get an idea to scan it will get nothing readable.

Other requirements:

  • should not be complicated
  • it should not consist of RSA, PKI infrastructure, key pairs, etc.

It must be simple enough to get rid of the people snooping around, and easy to decrypt for other companies interested in getting that data. They call us, we tell them the standard or give them some simple key which can then be used for decryption.

Probably those companies could use different technologies so it would be good to stick to some standard which is not tied to some special platform or technology.

What do you suggest? Is there some Java class doing encrypt() & decrypt() without much complication in achieving high security standards?

解决方案

This is the first page that shows up via Google and the security vulnerabilities in all the implementations make me cringe so I'm posting this to add information regarding encryption for others as it has been 7 Years from the original post. I hold a Masters Degree in Computer Engineering and spent a lot of time studying and learning Cryptography so I'm throwing my two cents to make the internet a safer place.

Also, do note that a lot of implementation might be secure for a given situation, but why use those and potentially accidentally make a mistake? Use the strongest tools you have available unless you have a specific reason not to. Overall I highly advise using a library and staying away from the nitty gritty details if you can.

UPDATE 4/5/18: I rewrote some parts to make them simpler to understand and changed the recommended library from Jasypt to Google's new library Tink, I would recommend completely removing Jasypt from an existing setup.

Foreword

I will outline the basics of secure symmetric cryptography below and point out common mistakes I see online when people implement crypto on their own with the standard Java library. If you want to just skip all the details run over to Google's new library Tink import that into your project and use AES-GCM mode for all your encryptions and you shall be secure.

Now if you want to learn the nitty gritty details on how to encrypt in java read on :)

Block Ciphers

First thing first you need to pick a symmetric key Block Cipher. A Block Cipher is a computer function/program used to create Pseudo-Randomness. Pseudo-Randomness is fake randomness that no computer other than a Quantum Computer would be able to tell the difference between it and real randomness. The Block Cipher is like the building block to cryptography, and when used with different modes or schemes we can create encryptions.

Now regarding Block Cipher Algorithms available today, Make sure to NEVER, I repeat NEVER use DES, I would even say NEVER use 3DES. The only Block Cipher that even Snowden's NSA release was able to verify being truly as close to Pseudo-Random as possible is AES 256. There also exists AES 128; the difference is AES 256 works in 256-bit blocks, while AES 128 works in 128 blocks. All in all, AES 128 is considered secure although some weaknesses have been discovered, but 256 is as solid as it gets.

Fun fact DES was broken by the NSA back when it was initially founded and actually kept a secret for a few years. Although some people still claim 3DES is secure, there are quite a few research papers that have found and analyzed weaknesses in 3DES.

Encryption Modes

Encryption is created when you take a block cipher and use a specific scheme so that the randomness is combined with a key to creating something that is reversible as long as you know the key. This is referred to as an Encryption Mode.

Here is an example of an encryption mode and the simplest mode known as ECB just so you can visually understand what is happening:

The encryption modes you will see most commonly online are the following:

ECB CTR, CBC, GCM

There exist other modes outside of the ones listed and researchers are always working toward new modes to improve existing problems.

Now let's move on to implementations and what is secure. NEVER use ECB this is bad at hiding repeating data as shown by the famous

When implementing in Java, note that if you use the following code, ECB mode is set by default:

Cipher cipher = Cipher.getInstance("AES");

... DANGER THIS IS A VULNERABILITY! and unfortunately, this is seen all over StackOverflow and online in tutorials and examples.

Nonces and IVs

In response to the issue found with ECB mode nounces also known as IVs were created. The idea is that we generate a new random variable and attach it to every encryption so that when you encrypt two messages that are the same they come out different. The beauty behind this is that an IV or nonce is public knowledge. That means an attacker can have access to this but as long as they don't have your key, they cant do anything with that knowledge.

Common issues I will see is that people will set the IV as a static value as in the same fixed value in their code. and here is the pitfall to IVs the moment you repeat one you actually compromise the entire security of your encryption.

Generating A Random IV

SecureRandom randomSecureRandom = SecureRandom.getInstance("SHA1PRNG");
byte[] iv = new byte[cipher.getBlockSize()];
randomSecureRandom.nextBytes(iv);
IvParameterSpec ivParams = new IvParameterSpec(iv);

Note: SHA1 is broken but I couldn't find how to implement SHA256 into this use case properly, so if anyone wants to take a crack at this and update it would be awesome! Also SHA1 attacks still are unconventional as it can take a few years on a huge cluster to crack. Check out details here.

CTR Implementation

No padding is required for CTR mode.

 Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");

CBC Implementation

If you choose to implement CBC Mode do so with PKCS7Padding as follows:

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

CBC and CTR Vulnerability and Why You Should Use GCM

Although some other modes such as CBC and CTR are secure they run into the issue where an attacker can flip the encrypted data, changing its value when decrypted. So let's say you encrypt an imaginary bank message "Sell 100", your encrypted message looks like this "eu23ng" the attacker changes one bit to "eu53ng" and all of a sudden when decrypted your message, it reads as "Sell 900".

To avoid this the majority of the internet uses GCM, and every time you see HTTPS they are probably using GCM. GCM signs the encrypted message with a hash and checks to verify that the message has not been changed using this signature.

I would avoid implementing GCM because of its complexity. You are better off using Googles new library Tink because here again if you accidentally repeat an IV you are compromising the key in the case with GCM, which is the ultimate security flaw. New researchers are working towards IV repeat resistant encryption modes where even if you repeat the IV the key is not in danger but this has yet to come mainstream.

Now if you do want to implement GCM, here is a link to a nice GCM implementation. However, I can not ensure the security or if its properly implemented but it gets the basis down. Also note with GCM there is no padding.

Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

Keys vs Passwords

Another very important note, is that when it comes to cryptography a Key and a Password are not the same things. A Key in cryptography needs to have a certain amount of entropy and randomness to be considered secure. This is why you need to make sure to use the proper cryptographic libraries to generate the key for you.

So you really have two implementations you can do here, the first is to use the code found on this StackOverflow thread for Random Key Generation. This solution uses a secure random number generator to create a key from scratch that you can the use.

The other less secure option is to use, user input such as a password. The issue as we discussed is that the password doesn't have enough entropy, so we would have to use PBKDF2, an algorithm that takes the password and strengthens it. Here is a StackOverflow implementation I liked. However Google Tink library has all this built in and you should take advantage of it.

Android Developers

One important point to point out here is know that your android code is reverse engineerable and most cases most java code is too. That means if you store the password in plain text in your code. A hacker can easily retrieve it. Usually, for these type of encryption, you want to use Asymmetric Cryptography and so on. This is outside the scope of this post so I will avoid diving into it.

An interesting reading from 2013: Points out that 88% of Crypto implementations in Android were done improperly.

Final Thoughts

Once again I would suggest avoid implementing the java library for crypto directly and use Google Tink, it will save you the headache as they have really done a good job of implementing all the algorithms properly. And even then make sure you check up on issues brought up on the Tink github, vulnerabilities popup here and there.

If you have any questions or feedback feel free to comment! Security is always changing and you need to do your best to keep up with it :)

这篇关于如何在 Java 中加密字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆