我需要加密的字符串会显示在2D条码中(PDF-417),所以当有人知道扫描的想法时,它就不会可读。
其他需求:
它必须足够简单,以摆脱被监视的人,并且必须易于对其他有兴趣获取该数据的公司解密。他们打电话给我们,我们告诉他们标准,或者给他们一些简单的密钥,然后可以将其用于解密。
那些公司可能会使用不同的技术,因此最好坚持不依赖于某些特殊平台或技术的某些标准。
你有什么建议?有一些Java类做encrypt()
和decrypt()
没有太多的并发症,实现高安全标准?
与CBC等其他模式不同,GCM模式不需要IV是不可预测的。唯一的要求是,对于具有给定密钥的每次调用,IV必须是唯一的。如果对于给定的密钥重复一次,则可能会损害安全性。一种简单的实现方法是使用来自强伪随机数生成器的随机IV,如下所示。
也可以将序列或时间戳记用作IV,但听起来可能不那么琐碎。例如,如果系统未正确跟踪持久存储中已用作IV的序列,则在系统重新引导后,调用可能会重复IV。同样,也没有完美的时钟。电脑时钟重新调整等。
此外,每2 ^ 32次调用后应旋转一次键。有关IV要求的更多详细信息,请参阅此答案和NIST建议。
考虑到以下几点,这是我刚刚在Java 8中编写的加密和解密代码。希望有人会发现这个有用:
字节数组可以使用以下方法清除:
Arrays.fill(clearTextMessageByteArray, Byte.MIN_VALUE);
但是,从Java 8开始,没有容易清除的方法,SecretKeyspec
并且SecretKey
由于这两个接口的实现似乎尚未实现destroy()
该接口的方法Destroyable
。在下面的代码中,编写了一个单独的方法来清除SecretKeySpec
和SecretKey
使用反射。
密钥应使用以下两种方法之一生成。
请注意,密钥是像密码一样的秘密,但是与供人使用的密码不同,密钥是供加密算法使用的,因此只能使用上述方式生成。
package com.sapbasu.javastudy;
import java.lang.reflect.Field;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Crypto {
private static final int AUTH_TAG_SIZE = 128; // bits
// NIST recommendation: "For IVs, it is recommended that implementations
// restrict support to the length of 96 bits, to
// promote interoperability, efficiency, and simplicity of design."
private static final int IV_LEN = 12; // bytes
// number of random number bytes generated before re-seeding
private static final double PRNG_RESEED_INTERVAL = Math.pow(2, 16);
private static final String ENCRYPT_ALGO = "AES/GCM/NoPadding";
private static final List<Integer> ALLOWED_KEY_SIZES = Arrays
.asList(new Integer[] {128, 192, 256}); // bits
private static SecureRandom prng;
// Used to keep track of random number bytes generated by PRNG
// (for the purpose of re-seeding)
private static int bytesGenerated = 0;
public 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 (!ALLOWED_KEY_SIZES.contains(key.getEncoded().length * 8)) {
throw new IllegalArgumentException("Size of key must be 128, 192 or 256");
}
Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
byte[] iv = getIV(IV_LEN);
GCMParameterSpec gcmParamSpec = new GCMParameterSpec(AUTH_TAG_SIZE, iv);
cipher.init(Cipher.ENCRYPT_MODE, key, gcmParamSpec);
byte[] messageCipher = cipher.doFinal(input);
// Prepend the IV with the message cipher
byte[] cipherText = new byte[messageCipher.length + IV_LEN];
System.arraycopy(iv, 0, cipherText, 0, IV_LEN);
System.arraycopy(messageCipher, 0, cipherText, IV_LEN,
messageCipher.length);
return cipherText;
}
public 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[] iv = new byte[IV_LEN];
System.arraycopy(input, 0, iv, 0, IV_LEN);
byte[] messageCipher = new byte[input.length - IV_LEN];
System.arraycopy(input, IV_LEN, messageCipher, 0, input.length - IV_LEN);
GCMParameterSpec gcmParamSpec = new GCMParameterSpec(AUTH_TAG_SIZE, iv);
Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
cipher.init(Cipher.DECRYPT_MODE, key, gcmParamSpec);
return cipher.doFinal(messageCipher);
}
public byte[] getIV(int bytesNum) {
if (bytesNum < 1) throw new IllegalArgumentException(
"Number of bytes must be greater than 0");
byte[] iv = new byte[bytesNum];
prng = Optional.ofNullable(prng).orElseGet(() -> {
try {
prng = SecureRandom.getInstanceStrong();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Wrong algorithm name", e);
}
return prng;
});
if (bytesGenerated > PRNG_RESEED_INTERVAL || bytesGenerated == 0) {
prng.setSeed(prng.generateSeed(bytesNum));
bytesGenerated = 0;
}
prng.nextBytes(iv);
bytesGenerated = bytesGenerated + bytesNum;
return iv;
}
private 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);
}
}
加密密钥主要可以通过两种方式生成:
没有任何密码
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(KEY_LEN, SecureRandom.getInstanceStrong());
SecretKey secretKey = keyGen.generateKey();
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getEncoded(),
"AES");
Crypto.clearSecret(secretKey);
// After encryption or decryption with key
Crypto.clearSecret(secretKeySpec);
带密码
SecureRandom random = SecureRandom.getInstanceStrong();
byte[] salt = new byte[32];
random.nextBytes(salt);
PBEKeySpec keySpec = new PBEKeySpec(password, salt, iterations,
keyLength);
SecretKeyFactory keyFactory =
SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
SecretKey secretKey = keyFactory.generateSecret(keySpec);
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getEncoded(),
"AES");
Crypto.clearSecret(secretKey);
// After encryption or decryption with key
Crypto.clearSecret(secretKeySpec);
我为flutter找到了加密包来加密和解密一条消息,我成功地加密和解密了,但没有成功地在一个cas中使用这个独立的设备,如图所示。 这是一个例子,我用一个静态字符串和一个随机数组成一个明文,它允许更改生成的密钥,当我解密时,发现静态字符串与正则表达式匹配 目前我找不到如何输入我的加密密钥(fesesgesgneslg465esg6es4g)我塞拉赫要做这样的事情 ---------按下时,我生成一
问题内容: 我在我的iPhone应用程序中使用Objective C中的加密类,但是我在努力通过Android应用程序在JAVA中使用相同的功能。我的加密代码如下: 我试图在JAVA中复制它,但是当我编码相同的数据时却得到了不同的字符串。所以我做错了事,但我无法弄清楚。这是我的JAVA代码: 谁能看到我要去哪里错了? 根据以下注释,我添加了getBytes,但是生成的字符串仍然不同: 问题答案:
我将我的. net webapi移植到. net core webapi。在我使用的旧代码中 为此,我使用了库 但在移植到.net core之后,我面临的问题是: 对此的解决方案是什么?
使用lib中的模块在python中解密和加密字符串。最简单的方法 现在我想解密我之前输入的字符串。。
问题内容: 如果我有一个字符串变量: 我想在每一个前面加一个转义字符和 变量中 (即 未 竟逃脱字符),我该怎么做? 问题答案: 我不是在这里要求优雅,但我 认为 它可以满足您的要求(如果我误会了,请纠正我): 输出
问题内容: 我的意思是: 也许像: 在PHP中,您该怎么做? 尝试使用 ,但对我不起作用。 问题答案: 更新 PHP 7就绪版本。它使用PHP OpenSSL库中的openssl_encrypt函数。