Skip to content

Commit 714fe1d

Browse files
committed
Merge branch 'master' of gitlab.ext.cyber.ee:cdoc2/cdoc2-java-ref-impl
2 parents f3a9d15 + 886c75a commit 714fe1d

File tree

14 files changed

+463
-126
lines changed

14 files changed

+463
-126
lines changed

cdoc2-example-app/README.md

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,51 @@ Requirements:
1111
Configure cdoc2 maven dependencies: https://github.com/open-eid/cdoc2-java-ref-impl/tree/master?tab=readme-ov-file#maven-dependencies
1212

1313
```bash
14-
mvnw install
14+
mvn install
1515
```
1616

1717
## Run
1818

19-
Convert CDOC1 -> CDOC2 with password:
19+
20+
Install cdoc2-cli:
2021
```bash
21-
java -jar target/cdoc2-converter-1.0-SNAPSHOT.jar --cdoc=src/test/resources/cdoc/valid_cdoc11_ECC.cdoc2 -p12=src/test/resources/ecc/ecc.p12:test --cdoc2=out.cdoc2
22+
mvn dependency:copy -Dartifact=ee.cyber.cdoc2:cdoc2-cli:1.6.0 -DoutputDirectory=./target
2223
```
2324

24-
Install cdoc2-cli:
25+
Convert CDOC1 -> CDOC2 with password:
2526
```bash
26-
mvn dependency:copy -Dartifact=ee.cyber.cdoc2:cdoc2-cli:1.2.0 -DoutputDirectory=./target
27+
java -jar target/cdoc2-example-app-1.1-SNAPSHOT.jar cdoc-convert --cdoc=src/test/resources/cdoc/valid_cdoc11_ECC.cdoc -p12=src/test/resources/ecc/ecc.p12:test --cdoc2=out.cdoc2
2728
```
2829

2930
Decrypt `out.cdoc2`:
3031
```bash
31-
java -jar target/cdoc2-cli-1.2.0.jar decrypt --file=out.cdoc2 -pw
32+
java -jar target/cdoc2-cli-1.6.0.jar decrypt --file=out.cdoc2 -pw
3233
```
3334

35+
Create ASICE file:
36+
```bash
37+
java -jar target/cdoc2-example-app-1.1-SNAPSHOT.jar asic -f digidoc4j.asice README.md pom.xml
38+
```
39+
40+
#### `.asic` container encryption
41+
42+
* Files from unsigned `.asic` container are extracted before encryption, then encrypted/decrypted.
43+
* Signed `.asic` container is encrypted and decrypted without files extraction from it.
44+
`.asic` container opening and signature verification is a very extensive process and will take
45+
few minutes to print log messages in about 78MB. Read explanation [here](https://github.com/open-eid/digidoc4j/wiki/Questions-&-Answers#why-is-the-library-that-slow).
46+
Create signed container example `signed.asice` and test the encryption:
47+
48+
Encrypt signed ASICE -> CDOC2 with password:
49+
```bash
50+
java -jar target/cdoc2-example-app-1.1-SNAPSHOT.jar asic-convert --asic=src/test/resources/asic/signed.asice --cdoc2=signedAsic.cdoc2
51+
```
52+
53+
Encrypt non-signed ASICE -> CDOC2 with password:
54+
```bash
55+
java -jar target/cdoc2-example-app-1.1-SNAPSHOT.jar asic-convert --asic=src/test/resources/asic/no-signature.asice --cdoc2=extractedFiles.cdoc2 --tmp=/tmp
56+
```
57+
58+
3459
## Code Walkthrough
3560

3661
* `ee.cyber.cdoc2.converter.util.Util#reEncrypt` demonstrates howto decrypt CDOC1 file and create CDOC2

cdoc2-example-app/pom.xml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>ee.cyber.cdoc2.converter</groupId>
88
<artifactId>cdoc2-example-app</artifactId>
9-
<version>1.0-SNAPSHOT</version>
9+
<version>1.1-SNAPSHOT</version>
1010
<description>Example application for cdoc2 usage. Converts cdoc to cdoc2</description>
1111

1212
<properties>
@@ -35,7 +35,7 @@
3535
<dependency>
3636
<groupId>ee.cyber.cdoc2</groupId>
3737
<artifactId>cdoc2-lib</artifactId>
38-
<version>2.0.0</version>
38+
<version>3.0.0</version>
3939
</dependency>
4040
<dependency>
4141
<groupId>org.open-eid.cdoc4j</groupId>
@@ -67,6 +67,11 @@
6767
<artifactId>picocli</artifactId>
6868
<version>4.7.6</version>
6969
</dependency>
70+
<dependency>
71+
<groupId>org.digidoc4j</groupId>
72+
<artifactId>digidoc4j</artifactId>
73+
<version>6.0.0</version>
74+
</dependency>
7075
</dependencies>
7176

7277
<build>
@@ -94,7 +99,7 @@
9499
<transformers>
95100
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
96101
<manifestEntries>
97-
<Main-Class>ee.cyber.cdoc2.converter.ConverterCmd</Main-Class>
102+
<Main-Class>ee.cyber.cdoc2.converter.CDocConverterCli</Main-Class>
98103
</manifestEntries>
99104
</transformer>
100105
</transformers>
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package ee.cyber.cdoc2.converter;
2+
3+
import ee.cyber.cdoc2.converter.util.CommonService;
4+
import ee.cyber.cdoc2.converter.util.Util;
5+
import org.slf4j.Logger;
6+
import org.slf4j.LoggerFactory;
7+
import org.digidoc4j.Container;
8+
import org.digidoc4j.ContainerOpener;
9+
import org.digidoc4j.ContainerValidationResult;
10+
import org.digidoc4j.DataFile;
11+
import picocli.CommandLine;
12+
import picocli.CommandLine.Command;
13+
import picocli.CommandLine.Option;
14+
15+
import java.io.File;
16+
import java.nio.file.Path;
17+
import java.util.ArrayList;
18+
import java.util.List;
19+
import java.util.concurrent.Callable;
20+
21+
@Command(name = "asic-convert")
22+
@SuppressWarnings("squid:S106")
23+
public class AsicConverterCmd implements Callable<Void> {
24+
25+
private static final Logger log = LoggerFactory.getLogger(AsicConverterCmd.class);
26+
27+
@Option(names = {"-f", "-a", "--asic" }, required = true,
28+
paramLabel = "ASIC", description = "the ASIC file")
29+
File asicFile;
30+
31+
@Option(names = {"-o", "--out", "--cdoc2"}, required = false,
32+
paramLabel = "CDOC2", description = "the CDOC2 file")
33+
File cdoc2FileOption;
34+
35+
@Option(names = { "--tmp"}, required = false,
36+
paramLabel = "DIR",
37+
description = "temp directory used for temporary files extracted from ASIC container")
38+
Path tempDir = null;
39+
40+
@Option(names= {"--label"}, required = false,
41+
paramLabel = "label", description = "cdoc2 recipient label")
42+
String labelOption;
43+
44+
@Option(names = { "-h", "--help" }, usageHelp = false, description = "display a help message")
45+
private boolean helpRequested = false;
46+
47+
@Override
48+
public Void call() throws Exception {
49+
50+
char[] password = CommonService.askPassword();
51+
String label = CommonService.getLabel(labelOption);
52+
53+
File cdoc2File = CommonService.getCdoc2File(cdoc2FileOption, asicFile);
54+
55+
if (!asicFile.getPath().contains(".asic")) {
56+
throw new CommandLine.TypeConversionException(
57+
"Missing required file extension .asice for conversion"
58+
);
59+
}
60+
61+
encrypt(cdoc2File, asicFile, label, password);
62+
System.out.println("Created cdoc2 " + cdoc2File.getAbsolutePath());
63+
64+
return null;
65+
}
66+
67+
private void encrypt(File cdoc2OutFile, File incomingFile, String label, char[] password)
68+
throws Exception{
69+
70+
Container container = ContainerOpener.open(incomingFile.getPath());
71+
ContainerValidationResult result = container.validate();
72+
73+
boolean isContainerValid = result.isValid();
74+
if (!isContainerValid) {
75+
Util.encrypt(cdoc2OutFile, List.of(incomingFile), label, password);
76+
return;
77+
}
78+
79+
List<File> extractedFiles = checkSignatureOrExtractFiles(container, incomingFile);
80+
Util.encrypt(cdoc2OutFile, extractedFiles, label, password);
81+
}
82+
83+
private List<File> checkSignatureOrExtractFiles(
84+
Container container,
85+
File incomingFile
86+
) {
87+
if (!container.getSignatures().isEmpty()) {
88+
return List.of(incomingFile);
89+
} else {
90+
List<DataFile> dataFiles = container.getDataFiles();
91+
List<File> extractedFiles = new ArrayList<>();
92+
for (DataFile dataFile : dataFiles) {
93+
String incomingFilePath = incomingFile.getPath();
94+
String outFilePath =
95+
incomingFilePath.substring(0, incomingFilePath.lastIndexOf("/") + 1);
96+
String extractedFile = outFilePath + "/" + dataFile.getName();
97+
dataFile.saveAs(extractedFile);
98+
extractedFiles.add(new File(extractedFile));
99+
}
100+
return extractedFiles;
101+
}
102+
}
103+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package ee.cyber.cdoc2.converter;
2+
3+
import ee.cyber.cdoc2.converter.AsicConverterCmd;
4+
import ee.cyber.cdoc2.converter.CdocConverterCmd;
5+
import ee.cyber.cdoc2.converter.CreateAsicContainerCmd;
6+
7+
import picocli.CommandLine;
8+
import picocli.CommandLine.Command;
9+
import picocli.CommandLine.Option;
10+
11+
import java.util.concurrent.Callable;
12+
13+
@SuppressWarnings("java:S106")
14+
@Command(
15+
version = {"cdoc2-cli version: 1.6.0", "cdoc2-lib version: 3.0.0"},
16+
name = "cdoc2-example-app",
17+
header = "\r\ncdoc2-example-app is a command line interface for converting cdoc or asic "
18+
+ "documents to cdoc2\r\n",
19+
customSynopsis = { "cdoc [cdoc-convert] <arguments>",
20+
"cdoc [asic] <arguments>", "cdoc [asic-convert] <arguments>"},
21+
subcommands = {CdocConverterCmd.class, CreateAsicContainerCmd.class, AsicConverterCmd.class}
22+
)
23+
public class CDocConverterCli implements Callable<Void> {
24+
25+
public static void main(String... args) {
26+
if (args.length == 0) {
27+
CommandLine.usage(new CDocConverterCli(), System.out);
28+
CommandLine.usage(new CdocConverterCmd(), System.out);
29+
CommandLine.usage(new CreateAsicContainerCmd(), System.out);
30+
CommandLine.usage(new AsicConverterCmd(), System.out);
31+
}
32+
int exitCode = new CommandLine(new CDocConverterCli()).execute(args);
33+
34+
System.exit(exitCode);
35+
}
36+
37+
@Override
38+
public Void call() {
39+
return null;
40+
}
41+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package ee.cyber.cdoc2.converter;
2+
3+
import ee.cyber.cdoc2.converter.util.CommonService;
4+
import ee.cyber.cdoc2.converter.util.Util;
5+
import org.openeid.cdoc4j.token.Token;
6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
8+
import picocli.CommandLine;
9+
import picocli.CommandLine.Command;
10+
import picocli.CommandLine.Option;
11+
12+
import java.io.File;
13+
import java.io.FileInputStream;
14+
import java.io.InputStream;
15+
import java.nio.file.Path;
16+
import java.util.Objects;
17+
import java.util.concurrent.Callable;
18+
19+
@Command(name = "cdoc-convert")
20+
@SuppressWarnings("squid:S106")
21+
public class CdocConverterCmd implements Callable<Void> {
22+
23+
private static final Logger log = LoggerFactory.getLogger(CdocConverterCmd.class);
24+
25+
@Option(names = {"-p12"}, required = true, paramLabel = "FILE.p12",
26+
description = "Load private key for decryption from .p12 file (FILE.p12:password)")
27+
String p12;
28+
29+
@Option(names = {"-f", "-c", "--cdoc" }, required = true,
30+
paramLabel = "CDOC", description = "the CDOC file")
31+
File cdocFile;
32+
33+
@Option(names = {"-o", "--out", "--cdoc2"}, required = false,
34+
paramLabel = "CDOC2", description = "the CDOC2 file")
35+
File cdoc2FileOption;
36+
37+
@Option(names = { "--tmp"}, required = false,
38+
paramLabel = "DIR", description = "temp directory used for temporary files extracted from CDOC")
39+
Path tempDir = null;
40+
41+
@Option(names= {"--label"}, required = false,
42+
paramLabel = "label", description = "cdoc2 recipient label")
43+
String labelOption;
44+
45+
@Option(names = { "-h", "--help" }, usageHelp = false, description = "display a help message")
46+
private boolean helpRequested = false;
47+
48+
@Override
49+
public Void call() throws Exception {
50+
51+
char[] password = CommonService.askPassword();
52+
String label = CommonService.getLabel(labelOption);
53+
54+
File cdoc2File = CommonService.getCdoc2File(cdoc2FileOption, cdocFile);
55+
56+
Objects.requireNonNull(p12);
57+
Token token = Util.readPkcs12Token(p12);
58+
59+
try (InputStream cdocIs = new FileInputStream(cdocFile)) {
60+
Util.reEncrypt(cdocIs, token, cdoc2File, label, password, tempDir);
61+
}
62+
63+
System.out.println("Created cdoc2 " + cdoc2File.getAbsolutePath());
64+
65+
return null;
66+
}
67+
}

0 commit comments

Comments
 (0)