- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
I want to decrypt and encrypt a string using chacha20
BouncyCaSTLeProvider 使用的是 chacha20 技术。所以我把它包括在 jar 里。并尝试了代码但无法工作。
PBE.java
public class PBE extends AppCompatActivity {
private static final String salt = "A long, but constant phrase that will be used each time as the salt.";
private static final int iterations = 2000;
private static final int keyLength = 256;
private static final SecureRandom random = new SecureRandom();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pbe);
try {
Security.insertProviderAt(new BouncyCastleProvider(), 1);
//Security.addProvider(new BouncyCastleProvider());
String passphrase = "The quick brown fox jumped over the lazy brown dog";
String plaintext = "Hello";
byte [] ciphertext = encrypt(passphrase, plaintext);
String recoveredPlaintext = decrypt(passphrase, ciphertext);
TextView decryptedTv = (TextView) findViewById(R.id.tv_decrypt);
decryptedTv.setText(recoveredPlaintext);
System.out.println(recoveredPlaintext);
}catch (Exception e){
e.printStackTrace();
}
}
private static byte [] encrypt(String passphrase, String plaintext) throws Exception {
SecretKey key = generateKey(passphrase);
Cipher cipher = Cipher.getInstance("AES/CTR/NOPADDING");//,new BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE, key, generateIV(cipher), random);
return cipher.doFinal(plaintext.getBytes());
}
private static String decrypt(String passphrase, byte [] ciphertext) throws Exception {
SecretKey key = generateKey(passphrase);
Cipher cipher = Cipher.getInstance("AES/CTR/NOPADDING");// , new BouncyCastleProvider());
cipher.init(Cipher.DECRYPT_MODE, key, generateIV(cipher), random);
return new String(cipher.doFinal(ciphertext));
}
private static SecretKey generateKey(String passphrase) throws Exception {
PBEKeySpec keySpec = new PBEKeySpec(passphrase.toCharArray(), salt.getBytes(), iterations, keyLength);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWITHSHA256AND256BITAES-CBC-BC");
return keyFactory.generateSecret(keySpec);
}
private static IvParameterSpec generateIV(Cipher cipher) throws Exception {
byte [] ivBytes = new byte[cipher.getBlockSize()];
random.nextBytes(ivBytes);
return new IvParameterSpec(ivBytes);
}
}
但它没有给我正确的结果..
编辑和更新代码
public class ChaCha20Encryptor implements Encryptor {
private final byte randomIvBytes[] = {0, 1, 2, 3, 4, 5, 6, 7};
static {
Security.addProvider(new BouncyCastleProvider());
}
@Override
public byte[] encrypt(byte[] data, byte[] randomKeyBytes) throws IOException, InvalidKeyException,
InvalidAlgorithmParameterException, InvalidCipherTextException {
ChaChaEngine cipher = new ChaChaEngine();
CipherParameters cp = new KeyParameter(getMyKey(randomKeyBytes));
cipher.init(true, new ParametersWithIV(cp , randomIvBytes));
//cipher.init(true, new ParametersWithIV(new KeyParameter(randomKeyBytes), randomIvBytes));
byte[] result = new byte[data.length];
cipher.processBytes(data, 0, data.length, result, 0);
return result;
}
@Override
public byte[] decrypt(byte[] data, byte[] randomKeyBytes)
throws InvalidKeyException, InvalidAlgorithmParameterException, IOException,
IllegalStateException, InvalidCipherTextException {
ChaChaEngine cipher = new ChaChaEngine();
CipherParameters cp = new KeyParameter(getMyKey(randomKeyBytes));
cipher.init(false, new ParametersWithIV(cp , randomIvBytes));
//cipher.init(false, new ParametersWithIV(new KeyParameter(randomKeyBytes), randomIvBytes));
byte[] result = new byte[data.length];
cipher.processBytes(data, 0, data.length, result, 0);
return result;
}
@Override
public int getKeyLength() {
return 32;
}
@Override
public String toString() {
return "ChaCha20()";
}
private static byte[] getMyKey(byte[] key){
try {
//byte[] key = encodekey.getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 16); // use only first 128 bit
}
catch (NoSuchAlgorithmException e){
e.printStackTrace();
}
return key;
}
}
Now I have only problem decrypting. It shows an error that key must be 128 or 256 bits. What am I doing wrong.
最佳答案
与 AES 中的某些其他模式(如 CBC)不同,GCM 模式不要求 IV 不可预测(与 Chacha20-Poly1305 相同)。唯一的要求是 IV(对于 AES)或 nonce(对于 Chacha20-Poly1305)对于给定 key 的每次调用都必须是唯一的。如果它针对给定 key 重复一次,则可能会危及安全性。以良好的概率实现此目的的一种简单方法是使用来自强伪随机数生成器的随机 IV 或随机数,如下所示。 IV 或 nonce 冲突的概率(假设有一个强随机源)最多为 2^-32,这足以阻止攻击者。
使用序列或时间戳作为 IV 或随机数也是可能的,但它可能不像听起来那么微不足道。例如,如果系统没有正确跟踪已在持久存储中用作 IV 的序列,则调用可能会在系统重启后重复 IV。同样,没有完美的时钟。计算机时钟重新调整等
此外, key 应在每 2^32 次调用后轮换。
SecureRandom.getInstanceStrong()
可用于生成加密强度高的随机数。
现在支持ChaCha20的是Java 11,下面是一个使用ChaCha20-Poly1305加解密的示例程序。
在 AES-GCM(一种经过身份验证的分组密码算法)上使用 ChaCha20-Poly1305(一种基于流密码的经过身份验证的加密算法)的可能原因是:
当 CPU 不提供专用 AES 指令时,ChaCha20-Poly1305 几乎比 AES 快 3 倍。 Intel处理器提供AES-NI指令集[1]
与 AES-GCM 的 IV 不同,ChaCha20-Poly1305 不需要随机数不可预测/随机。因此可以避免运行伪随机数生成器的开销
[2]
ChaCha20 不像 AES
[1] 不易受到缓存冲突计时攻击
package com.sapbasu.javastudy;
import java.lang.reflect.Field;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Objects;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.security.auth.Destroyable;
/**
*
* The possible reasons for using ChaCha20-Poly1305 which is a
* stream cipher based authenticated encryption algorithm
* 1. If the CPU does not provide dedicated AES instructions,
* ChaCha20 is faster than AES
* 2. ChaCha20 is not vulnerable to cache-collision timing
* attacks unlike AES
* 3. Since the nonce is not required to be random. There is
* no overhead for generating cryptographically secured
* pseudo random number
*
*/
public class CryptoChaCha20 {
private static final String ENCRYPT_ALGO = "ChaCha20-Poly1305/None/NoPadding";
private static final int KEY_LEN = 256;
private static final int NONCE_LEN = 12; //bytes
private static final BigInteger NONCE_MIN_VAL = new BigInteger("100000000000000000000000", 16);
private static final BigInteger NONCE_MAX_VAL = new BigInteger("ffffffffffffffffffffffff", 16);
private static BigInteger nonceCounter = NONCE_MIN_VAL;
public static byte[] encrypt(byte[] input, SecretKeySpec key)
throws Exception {
Objects.requireNonNull(input, "Input message cannot be null");
Objects.requireNonNull(key, "key cannot be null");
if (input.length == 0) {
throw new IllegalArgumentException("Length of message cannot be 0");
}
if (key.getEncoded().length * 8 != KEY_LEN) {
throw new IllegalArgumentException("Size of key must be 256 bits");
}
Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
byte[] nonce = getNonce();
IvParameterSpec ivParameterSpec = new IvParameterSpec(nonce);
cipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
byte[] messageCipher = cipher.doFinal(input);
// Prepend the nonce with the message cipher
byte[] cipherText = new byte[messageCipher.length + NONCE_LEN];
System.arraycopy(nonce, 0, cipherText, 0, NONCE_LEN);
System.arraycopy(messageCipher, 0, cipherText, NONCE_LEN,
messageCipher.length);
return cipherText;
}
public static byte[] decrypt(byte[] input, SecretKeySpec key)
throws Exception {
Objects.requireNonNull(input, "Input message cannot be null");
Objects.requireNonNull(key, "key cannot be null");
if (input.length == 0) {
throw new IllegalArgumentException("Input array cannot be empty");
}
byte[] nonce = new byte[NONCE_LEN];
System.arraycopy(input, 0, nonce, 0, NONCE_LEN);
byte[] messageCipher = new byte[input.length - NONCE_LEN];
System.arraycopy(input, NONCE_LEN, messageCipher, 0, input.length - NONCE_LEN);
IvParameterSpec ivParameterSpec = new IvParameterSpec(nonce);
Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
return cipher.doFinal(messageCipher);
}
/**
*
* This method creates the 96 bit nonce. A 96 bit nonce
* is required for ChaCha20-Poly1305. The nonce is not
* a secret. The only requirement being it has to be
* unique for a given key. The following function implements
* a 96 bit counter which when invoked always increments
* the counter by one.
*
* @return
*/
public static byte[] getNonce() {
if (nonceCounter.compareTo(NONCE_MAX_VAL) == -1) {
return nonceCounter.add(BigInteger.ONE).toByteArray();
} else {
nonceCounter = NONCE_MIN_VAL;
return NONCE_MIN_VAL.toByteArray();
}
}
/**
*
* Strings should not be used to hold the clear text message or the key, as
* Strings go in the String pool and they will show up in a heap dump. For the
* same reason, the client calling these encryption or decryption methods
* should clear all the variables or arrays holding the message or the key
* after they are no longer needed. Since Java 8 does not provide an easy
* mechanism to clear the key from {@code SecretKeySpec}, this method uses
* reflection to clear the key
*
* @param key
* The secret key used to do the encryption
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws NoSuchFieldException
* @throws SecurityException
*/
@SuppressWarnings("unused")
public static void clearSecret(Destroyable key)
throws IllegalArgumentException, IllegalAccessException,
NoSuchFieldException, SecurityException {
Field keyField = key.getClass().getDeclaredField("key");
keyField.setAccessible(true);
byte[] encodedKey = (byte[]) keyField.get(key);
Arrays.fill(encodedKey, Byte.MIN_VALUE);
}
}
并且,这是一个 JUnit 测试:
package com.sapbasu.javastudy;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.security.SecureRandom;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.junit.jupiter.api.Test;
public class CryptoChaCha20Test {
private int KEY_LEN = 256; // bits
@Test
public void whenDecryptCalled_givenEncryptedTest_returnsDecryptedBytes()
throws Exception {
char[] input = {'e', 'n', 'c', 'r', 'y', 'p', 't', 'i', 'o', 'n'};
byte[] inputBytes = convertInputToBytes(input);
KeyGenerator keyGen = KeyGenerator.getInstance("ChaCha20");
keyGen.init(KEY_LEN, SecureRandom.getInstanceStrong());
SecretKey secretKey = keyGen.generateKey();
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getEncoded(),
"ChaCha20");
CryptoChaCha20.clearSecret(secretKey);
byte[] encryptedBytes = CryptoChaCha20.encrypt(inputBytes, secretKeySpec);
byte[] decryptedBytes = CryptoChaCha20.decrypt(encryptedBytes, secretKeySpec);
CryptoChaCha20.clearSecret(secretKeySpec);
assertArrayEquals(inputBytes, decryptedBytes);
}
private byte[] convertInputToBytes(char[] input) {
CharBuffer charBuf = CharBuffer.wrap(input);
ByteBuffer byteBuf = Charset.forName(Charset.defaultCharset().name())
.encode(charBuf);
byte[] inputBytes = byteBuf.array();
charBuf.clear();
byteBuf.clear();
return inputBytes;
}
}
关于android - 使用 ChaCha20 加密和解密字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38007478/
我有一个 C# 应用程序调用 Java 网络服务来验证用户密码。我想让 C# 应用程序加密密码,然后让 Java Web 服务解密密码。我已经完成了 Java 端的代码(解密代码),但我无法找出 C#
我正在使用以下代码在使用 openssl 的 Windows 中使用 C 加密和解密二进制数据。如您所见,在这两个函数中,我都知道纯文本的大小。有什么方法可以在不知道纯文本大小的情况下解密消息? #i
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我有一个非常恼人的问题,Java中使用RSA算法对字符串进行不可靠的加密和解密。它似乎只能在大约 35% 的时间内工作,而且我不明白为什么它有时能工作,有时却不能。这是我写的一些测试代码,试图验证加密
我已经设法编写了用于文件加密/解密的函数。但它非常慢,尤其是随着文件大小的增加。例如几MB长的音频/视频文件 我几乎浏览了所有帖子来改进它,并尝试更改算法。如果有任何更改可以帮助我提高性能,请帮助我。
我正在尝试让我的转置密码发挥作用。 每当我将加密方法得到的密文输入解密方法时,我应该得到原始的明文......但事实并非如此...... 我做错了什么? 感谢您的帮助! public String E
我正在使用密码来加密和解密消息: public String encrypt(String string) throws InvalidKeyException, IllegalBlockSizeEx
我有一个在 MySQL 中存储数据的 spring-mvc 堆栈。其中一些数据需要保护,所以我想我应该加密它。由于我以后可能需要使用这些数据(信用卡、SSN 等),所以我需要对其进行解密。我认为这排除
作为一名SEOER,都想了解百度算法,通过算法原理来找到捷径的优化方案,那么今天我把研究多年的百度算法原理解密给大家,可能不是最好的,但是我可以给大家保证,这些都是非常实际的。希望给SEOER带来一
我试图找到一种技术来加密和解密程序中的文件,而无需将密码硬编码到程序中,也无需向用户询问密码。 如果我也可以从我正在编写的另一个程序中解密文件,那就太好了。 到目前为止,我还没有多少运气找到一种看起来
有没有一种方法可以使用作为字符串参数传递给程序的私钥而不是使用存储在机器上的证书来解密 PowerShell 中的 RSA?欢迎任何帮助,我的代码如下。 Function Decrypt-Asymme
通过问题Is it possible to use the Grails Jasypt plugin outside the GORM layer for simple String encrypti
我需要解密/加密我的域类中的几列,并且正在寻找有关如何做的信息。我已经找到了jasypt加密插件,但不幸的是它似乎与Grails 2.4不兼容。 我可能可以将一些东西拼凑在一起,但是想要确保Im遵循最
我需要有关声音文件加密/解密的帮助。我想在存储这个声音文件时加密一个声音文件,并在播放这个文件时解密它。我阅读了有关 java 中的加密/解密以及 java 中可用于此的大量示例代码。但这些程序不适用
我很感兴趣是否可以使用 Excel Visual Basic 和某些加密服务提供程序进行字符串加密/解密。 我找到了一个演练 Encrypting and Decrypting Strings in
我们正在使用加密/解密和UIIMAGE。如果我们在不保存到iphone画廊的情况下进行加密和解密以及UIIMAge,则可以正常工作,但是,如果我们进行加密,保存到画廊,将(加密的图像)加载到应用程序中
我正在做一个像这样的简单程序: package rsaexample; import java.io.*; import java.math.BigInteger; import java.secur
我发现这段代码返回给定字符串的校验和。 public static String getChecksum(String md5) { int counter = 0; while (c
我在 Java SE 和 Android 项目上使用相同的代码。在 Java 和 Android 中运行的应用程序连接到相同的 MQTT 代理并交换消息。消息使用 AES 进行加密/解密。我对 Jav
我想在 openssl/libcrypto 中使用 RSA 加密/解密一个长文件(我知道 AES 更好,但这只是为了比较)。我将输入文件分成大小为 numBlocks = inputFileLengt
我是一名优秀的程序员,十分优秀!