Repository navigation
Expand file tree
/
Copy pathSymmetricModesTest.java
More file actions
131 lines (122 loc) · 5.32 KB
/
Copy pathSymmetricModesTest.java
File metadata and controls
131 lines (122 loc) · 5.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package com.example.crypto.algorithms;
//import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.SecureRandom;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
/**
* SymmetricModesTest demonstrates the use of advanced cipher modes for
* symmetric encryption:
*
* 1. AES/KWP/NoPadding: Uses AES Key Wrap with Padding (KWP) to securely wrap
* (encrypt) a key. - Secure usage: Uses a randomly generated wrapping key.
*
* 2. AES/OFB8/NoPadding: Uses AES in Output Feedback mode with an 8-bit
* feedback size. - Secure usage: Uses a random IV for each encryption. -
* Insecure usage: Using a fixed IV (or nonce) in OFB mode compromises
* confidentiality.
*
* In production, algorithm parameters (such as mode, padding, and IV
* generation) should be externalized via configuration files to support crypto
* agility.
*/
public class SymmetricModesTest {
// static {
// // Register BouncyCastle provider for additional cipher modes.
// Security.addProvider(new BouncyCastleProvider());
// }
// ---------------------------
// AES/KWP/NoPadding Example
// ---------------------------
/**
* Securely wraps a target AES key using AES/KWP/NoPadding.
*
* Best Practice: - The wrapping key must be generated randomly. - AES/KWP
* provides key wrapping with padding, suitable for keys whose lengths are
* not multiples of the block size.
*
* @return The Base64-encoded wrapped key.
* @throws Exception if an error occurs during key wrapping.
*/
public String secureAESKWPWrap() throws Exception {
// Generate a random wrapping key (256-bit) for key wrapping.
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(256, new SecureRandom());
SecretKey wrappingKey = kg.generateKey();
// Generate a target AES key to be wrapped (128-bit).
kg.init(128, new SecureRandom());
SecretKey targetKey = kg.generateKey();
// Use AES/KWP (Key Wrap with Padding) to wrap the target key.
Cipher cipher = Cipher.getInstance("AES/KWP/NoPadding", "BC");
cipher.init(Cipher.WRAP_MODE, wrappingKey);
byte[] wrappedKey = cipher.wrap(targetKey);
return Base64.getEncoder().encodeToString(wrappedKey);
}
// ---------------------------
// AES/OFB8/NoPadding Examples
// ---------------------------
/**
* Securely encrypts plaintext using AES in OFB mode with an 8-bit feedback
* size (AES/OFB8/NoPadding).
*
* Best Practice: - Use a fresh, random IV for each encryption operation.
*
* @param key The AES key.
* @param plaintext The plaintext to encrypt.
* @return The ciphertext (Base64-encoded) with the IV prepended.
* @throws Exception if encryption fails.
*/
public String secureAesOfb8Encryption(SecretKey key, byte[] plaintext) throws Exception {
Cipher cipher = Cipher.getInstance("AES/OFB8/NoPadding", "BC");
byte[] iv = new byte[16]; // IV size for AES block cipher (128-bit) even if feedback is 8-bit.
new SecureRandom().nextBytes(iv);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] ciphertext = cipher.doFinal(plaintext);
// Prepend IV to ciphertext (as is common practice)
byte[] output = new byte[iv.length + ciphertext.length];
System.arraycopy(iv, 0, output, 0, iv.length);
System.arraycopy(ciphertext, 0, output, iv.length, ciphertext.length);
return Base64.getEncoder().encodeToString(output);
}
/**
* Insecurely encrypts plaintext using AES in OFB mode with an 8-bit
* feedback size (AES/OFB8/NoPadding) by using a fixed IV.
*
* Best Practice Violation: - Using a fixed IV (or nonce) with any
* encryption mode (including OFB) compromises the cipher's security.
*
* @param key The AES key.
* @param plaintext The plaintext to encrypt.
* @return The ciphertext (Base64-encoded) with the fixed IV prepended.
* @throws Exception if encryption fails.
*/
public String insecureAesOfb8Encryption(SecretKey key, byte[] plaintext) throws Exception {
Cipher cipher = Cipher.getInstance("AES/OFB8/NoPadding", "BC");
// Fixed IV: Insecure because it causes nonce/IV reuse.
byte[] fixedIV = new byte[16]; // All zeros.
IvParameterSpec ivSpec = new IvParameterSpec(fixedIV);
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] ciphertext = cipher.doFinal(plaintext);
byte[] output = new byte[fixedIV.length + ciphertext.length];
System.arraycopy(fixedIV, 0, output, 0, fixedIV.length);
System.arraycopy(ciphertext, 0, output, fixedIV.length, ciphertext.length);
return Base64.getEncoder().encodeToString(output);
}
// ---------------------------
// Helper Methods
// ---------------------------
/**
* Generates a secure 256-bit AES key.
*
* @return A new AES SecretKey.
* @throws Exception if key generation fails.
*/
public SecretKey generateAESKey() throws Exception {
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(256, new SecureRandom());
return kg.generateKey();
}
}