Skip to content

Commit c8b7702

Browse files
committed
Merge branch 'RM-3580' into 'master'
RM-3580: Validate KeyLabelParams in EncryptionKeyMaterial.from(TYPE, KeyLabelParams) See merge request cdoc2/cdoc2-java-ref-impl!34
2 parents 160cf3e + c664c7a commit c8b7702

File tree

14 files changed

+338
-157
lines changed

14 files changed

+338
-157
lines changed

cdoc2-cli/src/main/java/ee/cyber/cdoc2/cli/SymmetricKeyUtil.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,11 @@ public static FormattedOptionParts getSplitPasswordAndLabel(
206206
splitFormattedOption(formattedPassword, EncryptionKeyOrigin.PASSWORD);
207207
//overwrite label with recipient label to allow entering password without label for
208208
//single pbkdfRecipient eg -pw ":pw"
209-
return new FormattedOptionParts(parsed.optionChars(), label, EncryptionKeyOrigin.PASSWORD);
209+
return new FormattedOptionParts(
210+
parsed.optionChars(),
211+
parsed.label().isBlank() ? label : parsed.label(),
212+
EncryptionKeyOrigin.PASSWORD
213+
);
210214
}
211215
} else {
212216
return getSplitPasswordAndLabel(formattedPassword, false);

cdoc2-cli/src/test/java/CDocCliTest.java

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
import org.junit.jupiter.api.AfterEach;
1515
import org.junit.jupiter.api.BeforeEach;
16+
import org.junit.jupiter.api.Disabled;
1617
import org.junit.jupiter.api.Test;
1718
import org.junit.jupiter.api.function.Executable;
1819
import org.junit.jupiter.api.io.TempDir;
@@ -90,6 +91,21 @@ void testSuccessfulCreateDecryptDocWithPassword() throws IOException {
9091
decrypt(PASSWORD_OPTION, SUCCESSFUL_EXIT_CODE);
9192
}
9293

94+
@Test
95+
@Disabled
96+
void testSuccessfulCreateDecryptDocWithPasswordWhenItIsInsertedInteractively()
97+
throws IOException {
98+
encrypt(PASSWORD_OPTION);
99+
decrypt("--password=", SUCCESSFUL_EXIT_CODE);
100+
}
101+
102+
@Test
103+
void testSuccessfulCreateDecryptDocWithPasswordWhenLabelIsMissing()
104+
throws IOException {
105+
encrypt(PASSWORD_OPTION);
106+
decrypt("--password=:myPlainTextPassword", SUCCESSFUL_EXIT_CODE);
107+
}
108+
93109
@Test
94110
void testSuccessfulCreateDecryptDocWithSecret() throws IOException {
95111
encrypt(SECRET_OPTION);
@@ -203,15 +219,15 @@ void infoShouldDisplayKeyLabelInDefaultFormatForPassword() throws IOException {
203219

204220
@Test
205221
void infoShouldDisplayKeyLabelInPlainText() throws IOException {
206-
disableKeyLabelFormatting();
222+
setUpKeyLabelFormat(false);
207223

208224
encrypt(PASSWORD_OPTION);
209225
decrypt(PASSWORD_OPTION, SUCCESSFUL_EXIT_CODE);
210226

211227
String expectedKeyLabel = "Password: LABEL:passwordlabel";
212228
executeInfo(expectedKeyLabel, cdocFile);
213229

214-
restoreDefaultKeyLabelFormat();
230+
setUpKeyLabelFormat(true);
215231
}
216232

217233
@Test
@@ -226,15 +242,15 @@ void infoShouldDisplayKeyLabelInDefaultFormatForSecret() throws IOException {
226242

227243
@Test
228244
void infoShouldDisplayKeyLabelInPlainTextForSecret() throws IOException {
229-
disableKeyLabelFormatting();
245+
setUpKeyLabelFormat(false);
230246

231247
encrypt(SECRET_OPTION);
232248
decrypt(SECRET_OPTION, SUCCESSFUL_EXIT_CODE);
233249

234250
String expectedKeyLabel = "SymmetricKey: LABEL:label_b64secret";
235251
executeInfo(expectedKeyLabel, cdocFile);
236252

237-
restoreDefaultKeyLabelFormat();
253+
setUpKeyLabelFormat(true);
238254
}
239255

240256
@Test
@@ -556,19 +572,11 @@ private static Map<String, String> convertStringToKeyLabelParamsMap(String data)
556572
return result;
557573
}
558574

559-
private void disableKeyLabelFormatting() {
560-
Properties props = System.getProperties();
561-
props.setProperty(
562-
"ee.cyber.cdoc2.key-label.machine-readable-format.enabled",
563-
"false"
564-
);
565-
}
566-
567-
private void restoreDefaultKeyLabelFormat() {
575+
private void setUpKeyLabelFormat(boolean isFormatted) {
568576
Properties props = System.getProperties();
569577
props.setProperty(
570578
"ee.cyber.cdoc2.key-label.machine-readable-format.enabled",
571-
"true"
579+
String.valueOf(isFormatted)
572580
);
573581
}
574582

cdoc2-lib/src/main/java/ee/cyber/cdoc2/crypto/KeyLabelParams.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package ee.cyber.cdoc2.crypto;
22

33
import java.util.Map;
4+
import java.util.Objects;
5+
46
import static ee.cyber.cdoc2.crypto.KeyLabelTools.urlEncodeValue;
57

68

@@ -19,15 +21,14 @@ public KeyLabelParams addParam(String key, String value) {
1921
return this;
2022
}
2123

22-
//ToDo RM-3549
23-
// public boolean hasParam(String key) {
24-
// Objects.requireNonNull(key);
25-
// return true;
26-
// }
27-
//
28-
// public boolean isFromOrigin(EncryptionKeyOrigin origin) {
29-
// Objects.requireNonNull(origin);
30-
// return true;
31-
// }
24+
public boolean hasParam(KeyLabelTools.KeyLabelDataFields key) {
25+
Objects.requireNonNull(key);
26+
return this.keyLabelParams.containsKey(key.name());
27+
}
28+
29+
public boolean isFromOrigin(EncryptionKeyOrigin origin) {
30+
Objects.requireNonNull(origin);
31+
return this.encryptionKeyOrigin.equals(origin);
32+
}
3233

3334
}

cdoc2-lib/src/main/java/ee/cyber/cdoc2/crypto/KeyLabelTools.java

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -48,26 +48,16 @@ public static String formatKeyLabel(KeyLabelParams keyLabelParams) {
4848
}
4949

5050
/**
51-
* Validates encryption key label with decryption key label.
52-
* @param encryptionKeyLabel encryption key label
53-
* @param decryptionKeyLabel decryption key label
54-
* @return Key Label in the same format as it used for encryption
51+
* Validates key label format.
52+
* @param keyLabel encryption key label
53+
* @return Key Label in plain text
5554
*/
56-
public static Object checkKeyLabelFormatAndGet(
57-
Object encryptionKeyLabel,
58-
Object decryptionKeyLabel
59-
) {
60-
if (encryptionKeyLabel.equals(decryptionKeyLabel)) {
61-
return decryptionKeyLabel;
62-
}
63-
if (keyLabelIsFormatted(encryptionKeyLabel) && !keyLabelIsFormatted(decryptionKeyLabel)) {
64-
String encryptedKeyLabel = extractKeyLabel(encryptionKeyLabel.toString());
65-
if (null != encryptedKeyLabel && encryptedKeyLabel.equals(decryptionKeyLabel)) {
66-
return encryptionKeyLabel;
67-
}
55+
public static String getPlainKeyLabel(String keyLabel) {
56+
if (keyLabelIsFormatted(keyLabel)) {
57+
return extractKeyLabel(keyLabel);
6858
}
6959

70-
return decryptionKeyLabel;
60+
return keyLabel;
7161
}
7262

7363
/**
@@ -219,7 +209,7 @@ public static KeyLabelParams createSecretKeyLabelParams(String keyLabel) {
219209
KeyLabelParams keyLabelParams = createSymmetricKeyLabelParams(
220210
EncryptionKeyOrigin.SECRET, keyLabel
221211
);
222-
//ToDo add correct file, not payload file RM-3549
212+
//ToDo add correct file, not payload file RM-3648
223213
// if (isKeyLabelFileNameAllowedToBeAdded()) {
224214
// keyLabelParams.addParam(KeyLabelDataFields.FILE.name(), payloadFileName);
225215
// }

cdoc2-lib/src/main/java/ee/cyber/cdoc2/crypto/SymmetricKeyTools.java

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
import ee.cyber.cdoc2.crypto.keymaterial.EncryptionKeyMaterial;
1515
import ee.cyber.cdoc2.FormattedOptionParts;
1616

17-
import static ee.cyber.cdoc2.crypto.KeyLabelTools.checkKeyLabelFormatAndGet;
17+
import static ee.cyber.cdoc2.crypto.KeyLabelTools.getPlainKeyLabel;
18+
import static ee.cyber.cdoc2.crypto.KeyLabelTools.isFormatted;
1819

1920

2021
/**
@@ -26,20 +27,19 @@ private SymmetricKeyTools() { }
2627

2728
/**
2829
* Extract decryption key material from password.
29-
* @param passwordAndLabel split password and label
30+
* @param pwAndLabel split password and label
3031
* @param recipients the list of recipients
3132
* @return DecryptionKeyMaterial created from password
3233
*/
3334
public static DecryptionKeyMaterial extractDecryptionKeyMaterialFromPassword(
34-
FormattedOptionParts passwordAndLabel,
35+
FormattedOptionParts pwAndLabel,
3536
List<Recipient> recipients
3637
) {
3738
for (Recipient recipient : recipients) {
38-
if (recipient instanceof PBKDF2Recipient) {
39-
39+
if (keyLabelMatches(recipient, EncryptionKeyOrigin.PASSWORD, pwAndLabel.label())) {
4040
return DecryptionKeyMaterial.fromPassword(
41-
passwordAndLabel.optionChars(),
42-
passwordAndLabel.label()
41+
pwAndLabel.optionChars(),
42+
recipient.getRecipientKeyLabel()
4343
);
4444
}
4545
}
@@ -57,14 +57,11 @@ public static DecryptionKeyMaterial extractDecryptionKeyMaterialFromSecret(
5757
List<Recipient> recipients
5858
) {
5959
for (Recipient recipient : recipients) {
60-
Object decryptionKeyLabel = checkKeyLabelFormatAndGet(
61-
recipient.getRecipientKeyLabel(),
62-
secretAndLabel.label()
63-
);
64-
if (recipient instanceof SymmetricKeyRecipient
65-
&& recipient.getRecipientKeyLabel().equals(decryptionKeyLabel)) {
60+
if (keyLabelMatches(recipient, EncryptionKeyOrigin.SECRET, secretAndLabel.label())) {
6661
var entry = extractKeyMaterialFromSecret(secretAndLabel);
67-
return DecryptionKeyMaterial.fromSecretKey(decryptionKeyLabel.toString(), entry.getKey());
62+
return DecryptionKeyMaterial.fromSecretKey(
63+
entry.getKey(), recipient.getRecipientKeyLabel()
64+
);
6865
}
6966
}
7067
return null;
@@ -112,4 +109,32 @@ public static EncryptionKeyMaterial getEncryptionKeyMaterialFromPassword(
112109
return EncryptionKeyMaterial.fromPassword(splitPasswordAndLabel.optionChars(), splitPasswordAndLabel.label());
113110
}
114111

112+
private static boolean keyLabelMatches(
113+
Recipient recipient,
114+
EncryptionKeyOrigin keyOrigin,
115+
String requestedKeyLabel
116+
) {
117+
String recipientKeyLabel = recipient.getRecipientKeyLabel();
118+
String plainKeyLabel = getPlainKeyLabel(recipientKeyLabel);
119+
if (EncryptionKeyOrigin.PASSWORD == keyOrigin) {
120+
return passwordKeyLabelMatches(recipient, plainKeyLabel, requestedKeyLabel);
121+
} else if (EncryptionKeyOrigin.SECRET == keyOrigin) {
122+
return recipient instanceof SymmetricKeyRecipient
123+
&& plainKeyLabel.equals(requestedKeyLabel);
124+
}
125+
return false;
126+
}
127+
128+
private static boolean passwordKeyLabelMatches(
129+
Recipient recipient,
130+
String plainKeyLabel,
131+
String requestedKeyLabel
132+
) {
133+
if (isFormatted(requestedKeyLabel)) {
134+
return recipient instanceof PBKDF2Recipient
135+
&& recipient.getRecipientKeyLabel().equals(requestedKeyLabel);
136+
}
137+
return recipient instanceof PBKDF2Recipient && plainKeyLabel.equals(requestedKeyLabel);
138+
}
139+
115140
}

cdoc2-lib/src/main/java/ee/cyber/cdoc2/crypto/keymaterial/DecryptionKeyMaterial.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,16 @@ public interface DecryptionKeyMaterial {
2929
*/
3030
EncryptionKeyOrigin getKeyOrigin();
3131

32-
static DecryptionKeyMaterial fromSecretKey(String label, SecretKey secretKey) {
33-
return new SecretDecryptionKeyMaterial(label, secretKey);
32+
/**
33+
* Deprecated decryption key. Will be removed later.
34+
* Creates decryption key material with secret key.
35+
* @param secretKey secret key
36+
* @param label key label
37+
* @return DecryptionKeyMaterial key material required for decryption
38+
*/
39+
@Deprecated
40+
static DecryptionKeyMaterial fromSecretKey(SecretKey secretKey, String label) {
41+
return new SecretDecryptionKeyMaterial(secretKey, label);
3442
}
3543

3644
static DecryptionKeyMaterial fromPassword(char[] password, String label) {

cdoc2-lib/src/main/java/ee/cyber/cdoc2/crypto/keymaterial/EncryptionKeyMaterial.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import ee.cyber.cdoc2.crypto.EncryptionKeyOrigin;
44
import ee.cyber.cdoc2.crypto.KeyLabelParams;
5+
import ee.cyber.cdoc2.crypto.KeyLabelTools;
56
import ee.cyber.cdoc2.crypto.keymaterial.encrypt.EncryptionKeyMaterialCollectionBuilder;
67
import ee.cyber.cdoc2.crypto.keymaterial.encrypt.PasswordEncryptionKeyMaterial;
78
import ee.cyber.cdoc2.crypto.keymaterial.encrypt.PublicKeyEncryptionKeyMaterial;
@@ -70,10 +71,14 @@ static EncryptionKeyMaterial fromPublicKey(
7071
KeyLabelParams keyLabelParams
7172
) {
7273
Objects.requireNonNull(pubKey);
74+
EncryptionKeyOrigin origin = EncryptionKeyOrigin.PUBLIC_KEY;
75+
if (!keyLabelParams.isFromOrigin(origin)) {
76+
throw new IllegalArgumentException("KeyLabelParams must be of type " + origin);
77+
}
7378

7479
KeyLabelParams labelParams = (keyLabelParams == null)
7580
? createPublicKeyLabelParams(null, null)
76-
: keyLabelParams; //TODO: check params RM-3549
81+
: keyLabelParams;
7782

7883
return new PublicKeyEncryptionKeyMaterial(pubKey, formatKeyLabel(labelParams));
7984
}
@@ -119,13 +124,12 @@ static EncryptionKeyMaterial fromSecret(
119124
) {
120125
Objects.requireNonNull(preSharedKey);
121126
Objects.requireNonNull(keyLabelParams);
122-
// TODO: check params RM-3549
123-
// if (!keyLabelParams.isFromOrigin(EncryptionKeyOrigin.SECRET)
124-
// || !keyLabelParams.hasParam(KeyLabelTools.KeyLabelDataFields.LABEL.name())) {
125-
//
126-
// throw new IllegalArgumentException("keyLabelParams must have type "
127-
// + KeyLabelTools.KeyLabelType.SECRET + " and have a label");
128-
// }
127+
KeyLabelTools.KeyLabelDataFields label = KeyLabelTools.KeyLabelDataFields.LABEL;
128+
if (!keyLabelParams.isFromOrigin(EncryptionKeyOrigin.SECRET)
129+
|| !keyLabelParams.hasParam(label)) {
130+
throw new IllegalArgumentException("KeyLabelParams must be of type "
131+
+ KeyLabelTools.KeyLabelType.SECRET + " and have a parameter " + label);
132+
}
129133

130134
return new SecretEncryptionKeyMaterial(preSharedKey, formatKeyLabel(keyLabelParams));
131135
}
@@ -134,5 +138,4 @@ static EncryptionKeyMaterialCollectionBuilder collectionBuilder() {
134138
return new EncryptionKeyMaterialCollectionBuilder();
135139
}
136140

137-
138141
}

cdoc2-lib/src/main/java/ee/cyber/cdoc2/crypto/keymaterial/decrypt/SecretDecryptionKeyMaterial.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
import ee.cyber.cdoc2.crypto.KeyLabelTools;
99
import ee.cyber.cdoc2.crypto.keymaterial.DecryptionKeyMaterial;
1010

11+
1112
/**
1213
* Represents key material required for decryption with symmetric key derived from secret.
13-
*
14-
* @param keyLabel key label
1514
* @param secretKey symmetric key
15+
* @param keyLabel key label
1616
*/
1717
public record SecretDecryptionKeyMaterial(
18-
String keyLabel,
19-
SecretKey secretKey
18+
SecretKey secretKey,
19+
String keyLabel
2020
) implements DecryptionKeyMaterial, Destroyable {
2121

2222
@Override

0 commit comments

Comments
 (0)