Skip to content

Commit 0a6c74e

Browse files
authored
Fix #875: Update basic cryptography documentation (#876)
1 parent 34aca45 commit 0a6c74e

File tree

4 files changed

+434
-179
lines changed

4 files changed

+434
-179
lines changed

docs/Basic-definitions.md

Lines changed: 158 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,60 +8,68 @@ The following basic cryptography algorithms and parameters are used in the Power
88

99
### AES Symmetric Encryption
1010

11-
A symmetric key encryption algorithm, uses CBC mode of operation. It defines the following methods:
11+
A symmetric key encryption algorithm. The AES algorithm is used with 256-bit keys.
12+
13+
- CTR mode is used as the encryption primitive inside AEAD and for unauthenticated key wrapping (UKE).
14+
- GCM mode is used for local vault.
1215

1316
#### Encryption
1417

15-
Encrypt bytes using symmetric key with given initialization vector and `AES/CBC/PKCS7Padding` transformation:
18+
Encrypt bytes using symmetric key with given initialization vector and `AES/CTR/NoPadding` transformation:
1619

1720
```java
1821
byte[] encrypted = AES.encrypt(byte[] original, byte[] iv, SecretKey key);
1922
```
2023

21-
Encrypt bytes using symmetric key with given initialization vector and given cipher transformation.
24+
Encrypt bytes using symmetric key with given initialization vector and given cipher transformation:
2225

2326
```java
2427
byte[] encrypted = AES.encrypt(byte[] original, byte[] iv, SecretKey key, String transformation);
2528
```
2629

2730
#### Decryption
2831

29-
Decrypt bytes using symmetric key with given initialization vector and `AES/CBC/PKCS7Padding` transformation:
32+
Decrypt bytes using symmetric key with given initialization vector and `AES/CTR/NoPadding` transformation:
3033

3134
```java
3235
byte[] original = AES.decrypt(byte[] encrypted, byte[] iv, SecretKey key);
3336
```
3437

35-
Decrypt bytes using symmetric key with given initialization vector and given cipher transformation.
38+
Decrypt bytes using symmetric key with given initialization vector and given cipher transformation:
3639

3740
```java
3841
byte[] original = AES.decrypt(byte[] encrypted, byte[] iv, SecretKey key, String transformation);
3942
```
4043

41-
### PBKDF2
44+
### Generic KDF
4245

43-
An algorithm for key stretching, converts a short password into long key by performing repeated hash iteration on the original data. HMAC-SHA1 algorithm is used for a pseudo-random function. Implementations must make sure resulting key is converted into a format usable by the AES algorithm.
46+
Keys are derived from an original secret using hierarchical string labels to guarantee that derived keys are never reused for different purposes.
4447

45-
The following method will stretch the password using given number of iterations to achieve key of given length in bits. Use a provided salt value.
48+
The following method is used to derive a key from original secret value:
4649

4750
```java
48-
SecretKey expandedKey = PBKDF2.expand(char[] password, byte[] salt, long iterations, long lengthInBits);
51+
SecretKey derivedKey = KDF.derive(SecretKey sourceKey, String label);
4952
```
5053

54+
If raw bytes are required:
55+
56+
```java
57+
byte[] bytes = KDF.deriveBytes(byte[] secret, String label, int length);
58+
```
5159

52-
### X9.63 KDF with SHA256
60+
### Password KDF
5361

54-
A standard KDF function based on X9.63, with SHA256 as an internal hash function. It uses iterations of SHA256 hash function to derive a key of expected `length` of bytes.
62+
An algorithm for key stretching, converts a short password into long key by performing KMAC-based derivation on the original data.
5563

56-
Use the following method to derive a key of expected length from original secret value, using additional info byte value.
64+
The following method will stretch the password using provided salt:
5765

5866
```java
59-
byte[] bytes = KDF_X9_63_SHA256.derive(byte[] secret, byte[] info, int length);
67+
SecretKey expandedKey = KDF.derivePassword(byte[] password, byte[] salt);
6068
```
6169

6270
### ECDSA Signatures
6371

64-
An algorithm for elliptic curve based signatures, uses SHA256 hash algorithm and P256r1 EC curve. It defines the following operations:
72+
An algorithm for elliptic curve based signatures, uses SHA-384 hash algorithm and P-384 elliptic curve. It defines the following operations:
6573

6674
#### Data Signing
6775

@@ -79,60 +87,162 @@ Verify the signature for given data using a given public key.
7987
boolean isValid = ECDSA.verify(byte[] data, byte[] signature, PublicKey publicKey);
8088
```
8189

82-
### ECDH Key Agreement
90+
### ML-DSA Signatures
8391

84-
An algorithm for elliptic curve Diffie-Hellman, uses P256r1 curve. We define a single operation on ECDH, a symmetric key deduction between parties A and B:
92+
Post-quantum signature algorithm MLDSA can be used for post-quantum signatures.
8593

86-
Derive a shared secret using a private key of party A and a public key of party B using the follwing method.
94+
A ML-DSA key pair is generated with a specified variant of the algorithm:
95+
```java
96+
KeyPair keyPair = MLDSA.generateKeyPair(String algorithm); // ML-DSA-65 or ML-DSA-87
97+
```
8798

99+
A signature is created by signing the message raw bytes by private key from the ML-DSA keypair:
88100
```java
89-
SecretKey secretKey = ECDH.phase(PrivateKey privateKeyA, PublicKey publicKeyB);
101+
byte[] signature = MLDSA.sign(PrivateKey privateKey, byte[] message);
90102
```
91103

92-
### KDF
104+
A signature is verified for message raw bytes using public key from the ML-DSA keypair:
105+
```java
106+
boolean isValid = MLDSA.verify(PublicKey publicKey, byte[] message, byte[] signature);
107+
```
108+
109+
### KEM / ECDH Key Agreement
110+
111+
Generate KEM key pair:
112+
113+
```java
114+
KeyPair keyPair = KEM.generateKeyPair();
115+
```
116+
117+
Encapsulation:
118+
119+
```java
120+
Pair<SecretKey, byte[]> result = KEM.encapsulate(PublicKey publicKeyB);
121+
```
122+
123+
Decapsulation:
124+
125+
```java
126+
SecretKey secretKey = KEM.decapsulate(PrivateKey privateKeyA, byte[] ciphertext);
127+
```
128+
129+
The resulting `SecretKey` represents the shared secret between parties.
130+
131+
### SharedSecret Interface
93132

94-
A key derivation function used to derive a symmetric key with specific "index" from a given master key. Uses `AES` algorithm with the zero initialization vector to derive the new key in following way: `index` is converted to bytes, XORed with a 16 byte long zero array (to get 16 byte long array with bytes from the index) and AES encrypted using provided symmetric key `masterKey`.
133+
KEM is wrapped into a SharedSecret abstraction used by protocol flows.
95134

96-
To obtain a key derived from a master key using a provided index, use:
135+
Client derives shared secret from server response:
97136

98137
```java
99-
SecretKey derivedKey = KDF.derive(SecretKey masterKey, long index);
138+
SecretKey secretKey = SharedSecret.computeSharedSecret(
139+
SharedSecretClientContext context,
140+
SharedSecretResponse response
141+
);
100142
```
101143

102-
### KDF_INTERNAL
144+
The interface internally uses `SharedSecretRequest`, `SharedSecretResponse`, and `SharedSecretClientContext` objects.
103145

104-
A second key derivation function for the algorithm internal purposes used to derive a symmetric key with specific "index" (in this case, `byte[16]`) from a given master key. Uses `HMAC-SHA256` to derive the new key in following way:
146+
### UKE (Unauthenticated Key Encapsulation)
105147

106-
The `index` used as `HMAC-SHA256` key, provided symmetric key `masterKey` is converted to key bytes used as `HMAC-SHA256` data, resulting 32B long byte array is then XORed on per-byte basis (0th with 16th, 1st with 17th, etc.) to obtain 16B long byte array.
148+
Primitive used for protecting factor-related keys (for example knowledge or biometry).
107149

108-
To obtain a key derived from a master key using a provided index, use:
150+
UKE provides confidentiality without authentication and intentionally avoids authenticated encryption to prevent offline brute-force oracles on low-entropy secrets (such as PINs).
151+
152+
Wrap key using provided KEK:
153+
154+
```java
155+
byte[] wrapped = UKE.wrap(SecretKey key, SecretKey kek);
156+
```
157+
158+
Unwrap key using provided KEK:
109159

110160
```java
111-
SecretKey derivedKey = KDF_INTERNAL.derive(SecretKey masterKey, byte[] index);
161+
SecretKey key = UKE.unwrap(byte[] wrapped, SecretKey kek);
162+
```
163+
164+
### AEAD
165+
166+
Authenticated encryption used for End-To-End encryption and key protection.
167+
168+
A 12-byte unique nonce is used. For request/response flows, two independent nonces are used (one for request, one for response).
169+
170+
#### Seal
171+
172+
```java
173+
byte[] ciphertext = AEAD.seal(
174+
SecretKey key,
175+
byte[] keyContext,
176+
byte[] nonce,
177+
byte[] associatedData,
178+
byte[] plaintext
179+
);
180+
```
181+
182+
The nonce is prepended to the ciphertext during encryption.
183+
184+
#### Open
185+
186+
```java
187+
byte[] plaintext = AEAD.open(
188+
SecretKey key,
189+
byte[] keyContext,
190+
byte[] associatedData,
191+
byte[] ciphertext
192+
);
193+
```
194+
195+
The nonce is automatically extracted during decryption from ciphertext.
196+
197+
#### Extract Nonce
198+
199+
```java
200+
byte[] nonce = AEAD.extractNonce(byte[] ciphertext);
201+
```
202+
203+
AEAD internally derives encryption and authentication keys via KDF and authenticates data with KMAC-256.
204+
205+
### KDF
206+
207+
A key derivation function used to derive symmetric keys from a given master key.
208+
209+
A hierarchical KMAC-based derivation is used with string labels.
210+
211+
To obtain a key derived from a master key using a provided label:
212+
213+
```java
214+
SecretKey derivedKey = KDF.derive(SecretKey masterKey, String label);
215+
```
216+
217+
Example:
218+
219+
```java
220+
SecretKey KDK_UTILITY = KDF.derive(masterKey, "util");
221+
SecretKey KEY_STATUS = KDF.derive(KDK_UTILITY, "util/mac/status");
112222
```
113223

114224
## Helper Functions
115225

116226
These functions are used in the pseudo-codes:
117227

118-
### Key Generators.
228+
### Key Generators
119229

120230
#### Generate Random Key Pair
121231

122-
Generate a new EC key pair for the P256r1 elliptic curve.
232+
Generate a new EC key pair for the P-384 elliptic curve.
123233

124234
```java
125-
KeyPair keyPair = KeyGenerator.randomKeyPair();
235+
KeyPair keyPair = ECKeyGenerator.randomKeyPair("P-384");
126236
```
127237

128-
### Key Conversion Utilities.
238+
### Key Conversion Utilities
129239

130240
#### Convert Private Key to Bytes
131241

132242
Get bytes from the EC private key by encoding the D value (the number defining the EC private key).
133243

134244
```java
135-
byte[] privateKeyBytes = KeyConversion.getBytes(PrivateKey privKey)
245+
byte[] privateKeyBytes = KeyConversion.getBytes(PrivateKey privKey);
136246
```
137247

138248
#### Convert Bytes to Private Key
@@ -175,7 +285,7 @@ Create a symmetric key using provided bytes.
175285
SecretKey secretKey = KeyConversion.secretKeyFromBytes(byte[] secretKeyBytes);
176286
```
177287

178-
### Random Data Generators.
288+
### Random Data Generators
179289

180290
#### Generate Random Data
181291

@@ -214,29 +324,35 @@ String code = Generator.randomActivationCode();
214324
Function return an activation code from given random data.
215325

216326
```java
217-
String code = Generator.buildActivationCode(byte[10] randomBytes)
327+
String code = Generator.buildActivationCode(byte[10] randomBytes);
218328
```
219329

220330
### MAC Functions
221331

222-
#### HMAC-SHA256
332+
#### KMAC-256
223333

224-
Compute HMAC-SHA256 signature for given message using provided symmetric key.
334+
Compute KMAC-256 signature for given message using provided symmetric key.
225335

226336
```java
227-
byte[] signature = Mac.hmacSha256(SecretKey key, byte[] message);
337+
byte[] signature = Mac.kmac256(SecretKey key, byte[] message, int outLength, String custom);
228338
```
229339

230-
### Hashing Functions.
340+
### Hashing Functions
231341

232-
#### SHA256
342+
#### SHA3
233343

234-
Compute SHA256 hash of a given input.
344+
Compute SHA3 hash of a given input.
235345

236346
```java
237-
byte[] hash = Hash.sha256(byte[] original);
347+
byte[] hash = Hash.sha3_256(byte[] original);
238348
```
239349

350+
```java
351+
byte[] hash = Hash.sha3_384(byte[] original);
352+
```
353+
354+
Note: SHA-384 (SHA-2) is used internally by ECDSA signatures for compatibility reasons.
355+
240356
### Password Hashing
241357

242358
#### Compute Password Hash
@@ -255,7 +371,7 @@ Verify password against Argon2 hash stored in Modular Crypt Format.
255371
boolean matches = PasswordHash.verify(byte[] password, String hash);
256372
```
257373

258-
### Utility Functions.
374+
### Utility Functions
259375

260376
#### Obtain Zero Byte Array
261377

0 commit comments

Comments
 (0)