Skip to content

Commit d8fe143

Browse files
committed
Merge branch 'master' of gitlab.ext.cyber.ee:cdoc2/cdoc2-java-ref-impl
2 parents 0b3a013 + fcf96c3 commit d8fe143

File tree

4 files changed

+123
-44
lines changed

4 files changed

+123
-44
lines changed

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

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import ee.cyber.cdoc2.cli.CDocCli;
2+
23
import java.io.ByteArrayOutputStream;
34
import java.io.IOException;
45
import java.io.PrintStream;
56
import java.nio.charset.StandardCharsets;
67
import java.nio.file.Files;
78
import java.nio.file.Path;
89
import java.util.Base64;
10+
import java.util.Map;
911
import java.util.Properties;
12+
import java.util.TreeMap;
1013

1114
import org.junit.jupiter.api.AfterEach;
1215
import org.junit.jupiter.api.BeforeEach;
@@ -194,7 +197,7 @@ void infoShouldDisplayKeyLabelInDefaultFormatForPassword() throws IOException {
194197
encrypt(PASSWORD_OPTION);
195198
decrypt(PASSWORD_OPTION, SUCCESSFUL_EXIT_CODE);
196199

197-
String expectedKeyLabel = "Password: V:1, LABEL:passwordlabel, TYPE:pw ";
200+
String expectedKeyLabel = "Password: V:1, LABEL:passwordlabel, TYPE:pw";
198201
executeInfo(expectedKeyLabel, cdocFile);
199202
}
200203

@@ -205,7 +208,7 @@ void infoShouldDisplayKeyLabelInPlainText() throws IOException {
205208
encrypt(PASSWORD_OPTION);
206209
decrypt(PASSWORD_OPTION, SUCCESSFUL_EXIT_CODE);
207210

208-
String expectedKeyLabel = "Password: LABEL:passwordlabel ";
211+
String expectedKeyLabel = "Password: LABEL:passwordlabel";
209212
executeInfo(expectedKeyLabel, cdocFile);
210213

211214
restoreDefaultKeyLabelFormat();
@@ -217,7 +220,7 @@ void infoShouldDisplayKeyLabelInDefaultFormatForSecret() throws IOException {
217220
decrypt(SECRET_OPTION, SUCCESSFUL_EXIT_CODE);
218221

219222
String expectedKeyLabel
220-
= "SymmetricKey: V:1, LABEL:label_b64secret, TYPE:secret ";
223+
= "SymmetricKey: V:1, LABEL:label_b64secret, TYPE:secret";
221224
executeInfo(expectedKeyLabel, cdocFile);
222225
}
223226

@@ -228,7 +231,7 @@ void infoShouldDisplayKeyLabelInPlainTextForSecret() throws IOException {
228231
encrypt(SECRET_OPTION);
229232
decrypt(SECRET_OPTION, SUCCESSFUL_EXIT_CODE);
230233

231-
String expectedKeyLabel = "SymmetricKey: LABEL:label_b64secret ";
234+
String expectedKeyLabel = "SymmetricKey: LABEL:label_b64secret";
232235
executeInfo(expectedKeyLabel, cdocFile);
233236

234237
restoreDefaultKeyLabelFormat();
@@ -238,7 +241,7 @@ void infoShouldDisplayKeyLabelInPlainTextForSecret() throws IOException {
238241
void infoShouldDisplayKeyLabelInDefaultFormatForEc() throws IOException {
239242
successfullyDecryptDocWithPublicKey("keys/bob_pub.pem", "keys/bob.pem");
240243

241-
String expectedKeyLabel = "EC PublicKey: V:1, FILE:bob_pub.pem, TYPE:pub_key ";
244+
String expectedKeyLabel = "EC PublicKey: V:1, FILE:bob_pub.pem, TYPE:pub_key";
242245
executeInfo(expectedKeyLabel, cdocFile);
243246
}
244247

@@ -249,7 +252,7 @@ void infoShouldDisplayKeyLabelInDefaultFormatForRsa() throws IOException {
249252

250253
successfullyDecryptDocWithPublicKey(publicKey, privateKey);
251254

252-
String expectedKeyLabel = "RSA PublicKey: V:1, FILE:rsa_pub.pem, TYPE:pub_key ";
255+
String expectedKeyLabel = "RSA PublicKey: V:1, FILE:rsa_pub.pem, TYPE:pub_key";
253256
executeInfo(expectedKeyLabel, cdocFile);
254257
}
255258

@@ -521,7 +524,36 @@ private void executeInfo(String expectedKeyLabel, Path cdoc2File) {
521524
String[] split = outputWithoutBreaks.split("README.md");
522525
String actualOutputKeyLabel = split[split.length - 1];
523526

524-
assertEquals(expectedKeyLabel, actualOutputKeyLabel);
527+
assertEqualKeyLabels(expectedKeyLabel, actualOutputKeyLabel);
528+
}
529+
530+
private void assertEqualKeyLabels(String expectedKeyLabelMsg, String actualOutputKeyLabelMsg) {
531+
int delimiterIndexOfExpected = expectedKeyLabelMsg.indexOf(":");
532+
int delimiterIndexOfActual = actualOutputKeyLabelMsg.indexOf(":");
533+
String expectedKeyLabel = expectedKeyLabelMsg
534+
.substring(delimiterIndexOfExpected + 1).trim();
535+
String actualOutputKeyLabel = actualOutputKeyLabelMsg
536+
.substring(delimiterIndexOfActual + 1).trim();
537+
Map<String, String> expectedParams = convertStringToKeyLabelParamsMap(expectedKeyLabel);
538+
Map<String, String> actualParams = convertStringToKeyLabelParamsMap(actualOutputKeyLabel);
539+
540+
for (var entry : expectedParams.entrySet()) {
541+
assertTrue(actualParams.containsKey(entry.getKey()));
542+
assertTrue(actualParams.containsValue(entry.getValue()));
543+
}
544+
}
545+
546+
private static Map<String, String> convertStringToKeyLabelParamsMap(String data) {
547+
Map<String, String> result = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
548+
549+
String[] parts = data.split(", ");
550+
551+
for (String keyValue : parts) {
552+
String[] params = keyValue.split(":");
553+
result.put(params[0], params[1]);
554+
}
555+
556+
return result;
525557
}
526558

527559
private void disableKeyLabelFormatting() {

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

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
import java.net.URLEncoder;
99
import java.nio.charset.StandardCharsets;
1010
import java.util.Base64;
11-
import java.util.HashMap;
1211
import java.util.Locale;
1312
import java.util.Map;
13+
import java.util.TreeMap;
1414
import java.util.regex.Pattern;
1515
import java.util.stream.Collectors;
1616

@@ -25,6 +25,7 @@
2525
*/
2626
public final class KeyLabelTools {
2727

28+
private static final String DATA = "data:";
2829
private static final String DATA_DELIMITER = ",";
2930
private static final String DATA_PARAMETERS_DELIMITER = "&";
3031
private static final String DATA_PARAMETERS_KEY_VALUE_DELIMITER = "=";
@@ -61,7 +62,7 @@ public static Object checkKeyLabelFormatAndGet(
6162
}
6263
if (keyLabelIsFormatted(encryptionKeyLabel) && !keyLabelIsFormatted(decryptionKeyLabel)) {
6364
String encryptedKeyLabel = extractKeyLabel(encryptionKeyLabel.toString());
64-
if (encryptedKeyLabel.equals(decryptionKeyLabel)) {
65+
if (null != encryptedKeyLabel && encryptedKeyLabel.equals(decryptionKeyLabel)) {
6566
return encryptionKeyLabel;
6667
}
6768
}
@@ -96,13 +97,8 @@ public static Map<String, String> extractKeyLabelParams(String keyLabel) {
9697

9798
private static Map<String, String> decodeKeyLabelParamsFromUrlScheme(String keyLabel) {
9899
String keyLabelData = fromDataUrlScheme(keyLabel);
99-
Map<String, String> keyLabelParams = convertStringToKeyLabelParamsMap(keyLabelData);
100100

101-
return keyLabelParams.entrySet().stream()
102-
.collect(Collectors.toMap(
103-
Map.Entry::getKey,
104-
param -> urlDecodeValue(param.getValue()))
105-
);
101+
return convertStringToKeyLabelParamsMap(keyLabelData);
106102
}
107103

108104
/**
@@ -260,7 +256,7 @@ private static KeyLabelParams createKeyLabelCommonParams(
260256
EncryptionKeyOrigin encryptionKeyOrigin,
261257
KeyLabelTools.KeyLabelDataVersion version
262258
) {
263-
Map<String, String> keyLabelParams = new HashMap<>();
259+
Map<String, String> keyLabelParams = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
264260
keyLabelParams.put(
265261
KeyLabelDataFields.V.name(),
266262
urlEncodeValue(toNumbericString(version))
@@ -309,12 +305,15 @@ private static String extractKeyLabelByType(
309305
Map<String, String> keyLabelParams
310306
) {
311307
switch (keyLabelType) {
312-
case AUTH -> { // +
308+
case AUTH -> {
313309
return keyLabelParams.get(KeyLabelDataFields.PNO.name());
314310
}
315-
case PW, SECRET -> { // +
311+
case PW, SECRET -> {
316312
return keyLabelParams.get(KeyLabelDataFields.LABEL.name());
317313
}
314+
case PUB_KEY -> {
315+
return null;
316+
}
318317
default -> throw new IllegalArgumentException("Wrong key label type");
319318
}
320319
}
@@ -326,7 +325,7 @@ private static String extractKeyLabelByType(
326325
*/
327326
private static String toDataUrlScheme(String data) {
328327
StringBuilder sb = new StringBuilder();
329-
sb.append("data:");
328+
sb.append(DATA);
330329

331330
if (isEncoded(data)) {
332331
sb.append(BASE_64_DELIMITER + "base64");
@@ -357,15 +356,15 @@ private static String fromDataUrlScheme(String dataUrlScheme) {
357356
}
358357

359358
private static boolean keyLabelIsFormatted(Object keyLabel) {
360-
return keyLabel.toString().contains("data:");
359+
return keyLabel.toString().contains(DATA);
361360
}
362361

363362
public static boolean isFormatted(String keyLabel) {
364363
if (keyLabel == null) {
365364
return false;
366365
}
367366

368-
return keyLabel.startsWith("data:");
367+
return keyLabel.startsWith(DATA);
369368
}
370369

371370

@@ -395,7 +394,7 @@ private static String convertKeyLabelParamsMapToString(Map<String, String> map)
395394
}
396395

397396
private static Map<String, String> convertStringToKeyLabelParamsMap(String data) {
398-
Map<String, String> result = new HashMap<>();
397+
Map<String, String> result = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
399398
if (data.isBlank()) {
400399
return result;
401400
}
@@ -404,7 +403,7 @@ private static Map<String, String> convertStringToKeyLabelParamsMap(String data)
404403

405404
for (String keyValue : parts) {
406405
String[] params = keyValue.split(DATA_PARAMETERS_KEY_VALUE_DELIMITER);
407-
result.put(params[0], params[1]);
406+
result.put(params[0], urlDecodeValue(params[1]));
408407
}
409408

410409
return result;
@@ -441,8 +440,18 @@ public static String ofType(KeyLabelType type) {
441440
return type.name().toLowerCase(Locale.ROOT);
442441
}
443442

444-
public static KeyLabelType fromParams(String typeInLowerCase) {
445-
return KeyLabelType.valueOf(typeInLowerCase.toUpperCase());
443+
public static KeyLabelType fromParams(String type) {
444+
return KeyLabelType.getName(type);
445+
}
446+
447+
public static KeyLabelType getName(String keyLabelType) {
448+
for (var type : KeyLabelType.values()) {
449+
if (null != keyLabelType && type.name().compareToIgnoreCase(keyLabelType) == 0) {
450+
return type;
451+
}
452+
}
453+
454+
return null;
446455
}
447456
}
448457

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,44 @@
11
package ee.cyber.cdoc2;
22

3+
import ee.cyber.cdoc2.crypto.EncryptionKeyOrigin;
34
import ee.cyber.cdoc2.crypto.KeyLabelParams;
45
import ee.cyber.cdoc2.crypto.KeyLabelTools;
56
import org.junit.jupiter.api.Test;
67

78
import java.util.Map;
9+
import java.util.TreeMap;
810

911
import static org.junit.jupiter.api.Assertions.*;
1012

11-
class KeyLabelToolsTest {
1213

13-
static final KeyLabelParams defaultPubKeyParams =
14-
KeyLabelTools.createPublicKeyLabelParams(null, null);
15-
@Test
16-
void testFormatKeyLabel() {
17-
String actual = KeyLabelTools.formatKeyLabel(defaultPubKeyParams);
18-
String expected = "data:,V=1&TYPE=pub_key";
19-
assertEquals(expected, actual);
20-
}
14+
class KeyLabelToolsTest {
2115

2216
@Test
2317
void testExtractKeyLabelParams() {
2418
final String defaultPubKeyFormattedLabel = "data:,V=1&TYPE=pub_key";
2519
Map<String, String> paramsMap = KeyLabelTools.extractKeyLabelParams(defaultPubKeyFormattedLabel);
2620

2721
Map<String, String> expected = Map.of(
28-
"V", "1",
29-
"TYPE", "pub_key"
22+
"v", "1",
23+
"type", "pub_key"
3024
);
3125

3226
assertEquals(expected, paramsMap);
3327
}
28+
29+
@Test
30+
void testKeyLabelExtractionInSensitiveCase() {
31+
Map<String, String> paramsMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
32+
paramsMap.put("v", "1");
33+
paramsMap.put("tYpE", "pub_key");
34+
35+
KeyLabelParams params = new KeyLabelParams(
36+
EncryptionKeyOrigin.PUBLIC_KEY,
37+
paramsMap
38+
);
39+
40+
String formattedKeyLabel = KeyLabelTools.formatKeyLabel(params);
41+
assertDoesNotThrow(() -> KeyLabelTools.extractKeyLabel(formattedKeyLabel));
42+
}
43+
3444
}

test/bats/cdoc2_tests.bats

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,12 @@ EOF
382382
assertSuccessfulExitCode
383383
local expected_output_info="EC PublicKey: CERT_SHA1:5d5d9c00eeb79d89e3a54e791a6256f892ad9411, V:1, CN:cdoc20-client, FILE:cdoc2client-certificate.pem, TYPE:cert "
384384
echo "# $expected_output_info">&3
385-
assert_equal "$output" "$expected_output_info"
385+
assert_output --partial "EC PublicKey:"
386+
assert_output --partial "CERT_SHA1:5d5d9c00eeb79d89e3a54e791a6256f892ad9411"
387+
assert_output --partial "V:1"
388+
assert_output --partial "CN:cdoc20-client"
389+
assert_output --partial "FILE:cdoc2client-certificate.pem"
390+
assert_output --partial "TYPE:cert"
386391

387392
rm -f $TEST_RESULTS_DIR/$cdoc_file
388393
}
@@ -396,7 +401,12 @@ EOF
396401
assertSuccessfulExitCode
397402
local expected_output_info="EC PublicKey: CERT_SHA1:5d5d9c00eeb79d89e3a54e791a6256f892ad9411, V:1, CN:cdoc20-client, FILE:cdoc2client-certificate.pem, TYPE:cert "
398403
echo "# $expected_output_info">&3
399-
assert_equal "$output" "$expected_output_info"
404+
assert_output --partial "EC PublicKey:"
405+
assert_output --partial "CERT_SHA1:5d5d9c00eeb79d89e3a54e791a6256f892ad9411"
406+
assert_output --partial "V:1"
407+
assert_output --partial "CN:cdoc20-client"
408+
assert_output --partial "FILE:cdoc2client-certificate.pem"
409+
assert_output --partial "TYPE:cert"
400410

401411
# ensure encrypted container can be decrypted successfully
402412
run run_alias cdoc-cli decrypt -f $TEST_VECTORS_V_1_2/$existing_test_vector -k $CLI_KEYS_DIR/cdoc2client.pem -o $TEST_RESULTS_DIR
@@ -416,7 +426,10 @@ EOF
416426
assertSuccessfulExitCode
417427
local expected_output_info="RSA PublicKey: V:1, FILE:rsa_pub.pem, TYPE:pub_key "
418428
echo "# $expected_output_info">&3
419-
assert_equal "$output" "$expected_output_info"
429+
assert_output --partial "RSA PublicKey:"
430+
assert_output --partial "V:1"
431+
assert_output --partial "FILE:rsa_pub.pem"
432+
assert_output --partial "TYPE:pub_key"
420433

421434
rm -f $TEST_RESULTS_DIR/$cdoc_file
422435
}
@@ -430,7 +443,10 @@ EOF
430443
assertSuccessfulExitCode
431444
local expected_output_info="RSA PublicKey: V:1, FILE:rsa_pub.pem, TYPE:pub_key "
432445
echo "# $expected_output_info">&3
433-
assert_equal "$output" "$expected_output_info"
446+
assert_output --partial "RSA PublicKey:"
447+
assert_output --partial "V:1"
448+
assert_output --partial "FILE:rsa_pub.pem"
449+
assert_output --partial "TYPE:pub_key"
434450

435451
# ensure encrypted container can be decrypted successfully
436452
run run_alias cdoc-cli decrypt -f $TEST_VECTORS_V_1_2/$existing_test_vector -k $CLI_KEYS_DIR/rsa_priv.pem -o $TEST_RESULTS_DIR
@@ -449,7 +465,10 @@ EOF
449465
assertSuccessfulExitCode
450466
local expected_output_info="SymmetricKey: V:1, LABEL:$SECRET_LABEL, TYPE:secret "
451467
echo "# $expected_output_info">&3
452-
assert_equal "$output" "$expected_output_info"
468+
assert_output --partial "SymmetricKey:"
469+
assert_output --partial "V:1"
470+
assert_output --partial "LABEL:$SECRET_LABEL"
471+
assert_output --partial "TYPE:secret"
453472

454473
rm -f $TEST_RESULTS_DIR/$cdoc_file
455474
}
@@ -463,7 +482,10 @@ EOF
463482
assertSuccessfulExitCode
464483
local expected_output_info="SymmetricKey: V:1, LABEL:$SECRET_LABEL, FILE:$existing_test_vector, TYPE:secret "
465484
echo "# $expected_output_info">&3
466-
assert_equal "$output" "$expected_output_info"
485+
assert_output --partial "SymmetricKey:"
486+
assert_output --partial "V:1"
487+
assert_output --partial "LABEL:$SECRET_LABEL"
488+
assert_output --partial "TYPE:secret"
467489

468490
# ensure encrypted container can be decrypted successfully
469491
echo "# Decrypting ${existing_test_vector}">&3
@@ -486,7 +508,10 @@ EOF
486508
assertSuccessfulExitCode
487509
local expected_output_info="Password: V:1, LABEL:${PW_LABEL}, TYPE:pw "
488510
echo "# $expected_output_info">&3
489-
assert_equal "$output" "$expected_output_info"
511+
assert_output --partial "Password:"
512+
assert_output --partial "V:1"
513+
assert_output --partial "LABEL:${PW_LABEL}"
514+
assert_output --partial "TYPE:pw"
490515

491516
rm -f $TEST_RESULTS_DIR/$cdoc_file
492517
}
@@ -500,7 +525,10 @@ EOF
500525
assertSuccessfulExitCode
501526
local expected_output_info="Password: V:1, LABEL:${PW_LABEL}, TYPE:pw "
502527
echo "# $expected_output_info">&3
503-
assert_equal "$output" "$expected_output_info"
528+
assert_output --partial "Password:"
529+
assert_output --partial "V:1"
530+
assert_output --partial "LABEL:${PW_LABEL}"
531+
assert_output --partial "TYPE:pw"
504532

505533
# ensure encrypted container can be decrypted successfully
506534
echo "# Decrypting ${existing_test_vector}">&3

0 commit comments

Comments
 (0)