我想加密由webapp写的cookie,我想保持cookie的大小最小,因此我选择了AES/CTR/NoPadding.
你会建议使用什么作为IV足够随机并仍然保持应用程序无状态.我知道我可以生成随机IV并将其附加到消息中,但这会增加cookie的大小.
另外,对于128位AES,建议的IV大小是多少?
大家都这样做了吗?是否存在任何"经过尝试和真实"的方式?我不想重新发明轮子.
下面的代码片段突出显示了我当前使用AES密码和CTR操作模式实现的加密对象。
import javax.crypto.Cipher;
public abstract class Crypto {
private static final String CIPHER_ALGORITHM = "AES/CTR/NoPadding";
private String AesKeyString = "ByWelFHCgFqivFZrWs89LQ==";
private void setKey() throws NoSuchAlgorithmException{
byte[] keyBytes;
keyBytes = Base64.getDecoder().decode(AesKeyString);
aesKey = new SecretKeySpec(keyBytes, "AES");
}
protected byte[] execute(int mode, byte[] target, byte[] iv)
throws Exception{
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(mode, aesKey, ivSpec);
return cipher.doFinal(target);
}
}
Run Code Online (Sandbox Code Playgroud)
就我而言,getInstance()方法从支持此转换的第一个Provider返回一个实现请求的转换的Cipher对象。
以下是包含我所有可用提供商的列表:
SUN
Alg.Alias.Signature.SHA1/DSA SHA1withDSA
Alg.Alias.Signature.1.2.840.10040.4.3 SHA1withDSA
Alg.Alias.Signature.DSS SHA1withDSA
SecureRandom.SHA1PRNG ImplementedIn Software
KeyStore.JKS sun.security.provider.JavaKeyStore$DualFormatJKS …Run Code Online (Sandbox Code Playgroud) 我使用libgcrypt的CTR模式实现使用AES-256加密文件.我希望能够部分解密文件(例如,解密20个块中的5-10个块而不解密整个文件).
我知道通过使用CTR模式,我应该能够做到这一点.我所需要的只是知道正确的计数器.问题在于我所拥有的只是块0的初始计数器.例如,如果我想解密块5,我需要另一个计数器,通过对每个块的初始计数器执行一些操作来实现到5.
我似乎无法找到libgcrypt公开的API,以便为给定初始计数器的后续块计算计数器.
在给定块#0的计数器的情况下,如何计算后续块的计数器(例如块#5)?
据我所知,在AES计数器模式下,我需要使用128位随机数.这种天真的方法是使用一个随机的128位随机数,但我不确定如果它作为所有随机位传递,算法将能够正确递增计数器.我认为正确的方法是使用96位nonce以及从0开始的32位计数器,例如:
var key = CryptoJS.enc.Hex.parse('01ab23cd45ef67089a1b2c3d4e5f6a7b'); // 128 bits / 16 bytes
var nonce = '2301cd4ef785690a1b2c3dab'; // 96 bits / 12 bytes
var counter = '00000000'; // 32 bits / 4 bytes
var nonceAndCounter = nonce + counter;
nonceAndCounter = CryptoJS.enc.Hex.parse(nonceAndCounter);
var plaintext = 'The quick brown fox jumps over the lazy dog.';
var encryption = CryptoJS.AES.encrypt(plaintext, key, { iv: nonceAndCounter, mode: CryptoJS.mode.CTR, padding: CryptoJS.pad.NoPadding });
var ciphertext = encryption.ciphertext.toString(CryptoJS.enc.Hex);
Run Code Online (Sandbox Code Playgroud)
这是使用CryptoJS库执行此操作的正确方法吗?或者正确的方法是什么?
当我尝试使用相同的密钥再次加密密文时,它会生成原始的明文。
使用的算法是带有计数器模式的AES。Key和IV保持不变。
这是算法应该表现的方式吗?如果作为 Cipher.init() 的第一个参数给出的Cipher.ENCRYTMODE有什么用?
这是我测试过的示例程序,
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class EncryptionTest {
public static void main(String[] args) throws Exception {
SecretKeySpec key = null;
IvParameterSpec ivSpec = null;
byte[] keyBytes = "usethiskeyusethiusethiskeyusethi".getBytes();
byte[] ivBytes = "usethisIusethisI".getBytes();
key = new SecretKeySpec(keyBytes, "AES"); //No I18N
ivSpec = new IvParameterSpec(ivBytes);
Cipher AesCipher = Cipher.getInstance("AES/CTR/NoPadding");
byte[] byteText = "Your Plain Text Here".getBytes();
AesCipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] byteCipherText = AesCipher.doFinal(byteText);
System.out.println("Encrypted : …Run Code Online (Sandbox Code Playgroud) ctr-mode ×5
aes ×4
encryption ×3
cryptography ×2
java ×2
block-cipher ×1
cryptojs ×1
javascript ×1
javax.crypto ×1
jce ×1
libgcrypt ×1