diff options
| author | StevenWdV <stevenwdv@gmail.com> | 2022-01-24 14:59:25 +0100 |
|---|---|---|
| committer | StevenWdV <stevenwdv@gmail.com> | 2022-01-24 16:24:57 +0100 |
| commit | e544c6fa9e15e7277da79e2464243e90b2706b8c (patch) | |
| tree | de6613747e0e34a799089d4677f9833a85748712 /wrappers/java | |
| parent | aab2e4b966c82b67eb0e204060e5ea6cd4ea15cf (diff) | |
Cleanup
Added variables to Makefiles to specify custom exports/ directory;
Split exception classes in Java & C#;
Added more comments;
Renamed library and Go package;
Removed real (pure) tests;
Added generate_lib.ps1 to generate import .lib for Windows (Swift);
Moved built Go libraries to exports/lib/;
Switch to hopefully faster Swift GitHub Action.
Diffstat (limited to 'wrappers/java')
10 files changed, 113 insertions, 56 deletions
diff --git a/wrappers/java/Makefile b/wrappers/java/Makefile index 4b7b602..a63aef7 100644 --- a/wrappers/java/Makefile +++ b/wrappers/java/Makefile @@ -1,14 +1,21 @@ .PHONY: build pack test clean +EXPORTS_PATH ?= ../../exports +EXPORTS_LIB_PATH ?= $(EXPORTS_PATH)/lib + build: - mvn --no-transfer-progress compile + mvn --no-transfer-progress compile -DEXPORTS_LIB_PATH="$(EXPORTS_LIB_PATH)" pack: - mvn --no-transfer-progress package + mvn --no-transfer-progress package -DEXPORTS_LIB_PATH="$(EXPORTS_LIB_PATH)" test: - $(MAKE) -C ../../exports - mvn --no-transfer-progress test +ifneq ($(EXPORTS_PATH),) +ifneq ($(wildcard $(EXPORTS_PATH)/Makefile),) + $(MAKE) -C "$(EXPORTS_PATH)" +endif +endif + mvn --no-transfer-progress test -DEXPORTS_LIB_PATH="$(EXPORTS_LIB_PATH)" clean: rm -rf target/ diff --git a/wrappers/java/README.md b/wrappers/java/README.md index 87cdd49..b72d90e 100644 --- a/wrappers/java/README.md +++ b/wrappers/java/README.md @@ -16,7 +16,7 @@ Build `EduVpnCommon`: make ``` -Build as JAR, including eduvpn_verify library: +Build as JAR, including shared Go library: ```shell make pack diff --git a/wrappers/java/pom.xml b/wrappers/java/pom.xml index bd9f721..520bd34 100644 --- a/wrappers/java/pom.xml +++ b/wrappers/java/pom.xml @@ -10,9 +10,11 @@ <name>eduVPN common library</name> <properties> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <maven.compiler.source>1.8</maven.compiler.source> - <maven.compiler.target>1.8</maven.compiler.target> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.8</maven.compiler.target> + + <EXPORTS_LIB_PATH>../../exports/lib</EXPORTS_LIB_PATH> </properties> <dependencies> @@ -40,21 +42,21 @@ <!-- See com.sun.jna.Platform#getNativeLibraryResourcePrefix --> <resource> - <directory>../../exports/linux/amd64</directory> + <directory>${EXPORTS_LIB_PATH}/linux/amd64</directory> <includes> <include>*.so</include> </includes> <targetPath>linux-x86-64</targetPath> </resource> <resource> - <directory>../../exports/linux/arm</directory> + <directory>${EXPORTS_LIB_PATH}/linux/arm</directory> <includes> <include>*.so</include> </includes> <targetPath>linux-arm</targetPath> </resource> <resource> - <directory>../../exports/linux/arm64</directory> + <directory>${EXPORTS_LIB_PATH}/linux/arm64</directory> <includes> <include>*.so</include> </includes> @@ -62,36 +64,38 @@ </resource> <resource> - <directory>../../exports/windows/amd64</directory> + <directory>${EXPORTS_LIB_PATH}/windows/amd64</directory> <includes> <include>*.dll</include> </includes> <targetPath>win32-x86-64</targetPath> </resource> <resource> - <directory>../../exports/windows/386</directory> + <directory>${EXPORTS_LIB_PATH}/windows/386</directory> <includes> <include>*.dll</include> </includes> <targetPath>win32-x86</targetPath> </resource> <resource> - <directory>../../exports/windows/arm</directory> + <directory>${EXPORTS_LIB_PATH}/windows/arm</directory> <includes> <include>*.dll</include> </includes> <targetPath>win32-arm</targetPath> </resource> <resource> - <directory>../../exports/windows/arm64</directory> + <directory>${EXPORTS_LIB_PATH}/windows/arm64</directory> <includes> <include>*.dll</include> </includes> <targetPath>win32-arm64</targetPath> </resource> </resources> + <plugins> <plugin> + <!-- Test adapter --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> diff --git a/wrappers/java/src/main/java/nl/eduvpn/common/Discovery.java b/wrappers/java/src/main/java/nl/eduvpn/common/Discovery.java index 40d5300..69308c8 100644 --- a/wrappers/java/src/main/java/nl/eduvpn/common/Discovery.java +++ b/wrappers/java/src/main/java/nl/eduvpn/common/Discovery.java @@ -6,38 +6,48 @@ import java.nio.charset.StandardCharsets; import java.time.Instant; public final class Discovery { - private static final NativeApi discovery = Native.load("eduvpn_verify", NativeApi.class); + private static final String LIB_NAME = "eduvpn_common"; + private static final NativeApi discovery = Native.load(LIB_NAME, NativeApi.class); /** * Verifies the signature on the JSON server_list.json/organization_list.json file. - * If the function returns the signature is valid for the given file type. + * If the function returns, the signature is valid for the given file type. * * @param signature .minisig signature file contents. * @param signedJson Signed .json file contents. * @param expectedFileName The file type to be verified, one of {@code "server_list.json"} or {@code "organization_list.json"}. - * @param minSignTime Minimum time for signature. Should be set to at least the time in a previously retrieved file. + * @param minSignTime Minimum time for signature. Should be set to at least the time of the previous signature. * @throws IllegalArgumentException If {@code expectedFileName} is not one of the allowed values or one of the parameters is empty. * @throws VerifyException If signature verification fails. */ public static void verify(byte[] signature, byte[] signedJson, String expectedFileName, Instant minSignTime) throws VerifyException { - long err = discovery.Verify(NativeApi.GoSlice.make(signature), NativeApi.GoSlice.make(signedJson), - NativeApi.GoSlice.make(expectedFileName.getBytes(StandardCharsets.UTF_8)), - minSignTime.getEpochSecond()); - if (err != 0) { - if (err == 1) throw new IllegalArgumentException("Unknown excpectedFileName"); - throw new VerifyException(err); + byte err = discovery.Verify(NativeApi.GoSlice.fromArray(signature), NativeApi.GoSlice.fromArray(signedJson), + NativeApi.GoSlice.fromString(expectedFileName), minSignTime.getEpochSecond()); + + switch (err) { + case 0: + return; + case 1: + throw new IllegalArgumentException("unknown expected file name"); + case 2: + throw new InvalidSignatureException(); + case 3: + throw new InvalidSignatureUnknownKeyException(); + case 4: + throw new SignatureTooOldException(); + default: + throw new UnknownVerifyException(err); } } - /** - * Use for testing only, see Go documentation. - */ - // package-private + /** Use for testing only, see Go documentation. */ + /*package-private*/ static void insecureTestingSetExtraKey(String keyString) { - discovery.InsecureTestingSetExtraKey(NativeApi.GoSlice.make(keyString.getBytes(StandardCharsets.UTF_8))); + discovery.InsecureTestingSetExtraKey(NativeApi.GoSlice.fromArray(keyString.getBytes(StandardCharsets.UTF_8))); } private interface NativeApi extends Library { + // C-compatible structure @Structure.FieldOrder({"data", "len", "cap"}) class GoSlice extends Structure implements Structure.ByValue { public Pointer data; @@ -49,14 +59,19 @@ public final class Discovery { this.cap = cap; } - public static GoSlice make(byte[] bytes) { + public static GoSlice fromArray(byte[] bytes) { Memory memory = new Memory(bytes.length); memory.write(0, bytes, 0, bytes.length); return new GoSlice(memory, bytes.length, bytes.length); } + + /** From string as UTF-8. */ + public static GoSlice fromString(String str) { + return fromArray(str.getBytes(StandardCharsets.UTF_8)); + } } - long Verify(GoSlice signatureFileContent, GoSlice signedJson, GoSlice expectedFileName, long minSignTime); + byte Verify(GoSlice signatureFileContent, GoSlice signedJson, GoSlice expectedFileName, long minSignTime); void InsecureTestingSetExtraKey(GoSlice keyString); } diff --git a/wrappers/java/src/main/java/nl/eduvpn/common/InvalidSignatureException.java b/wrappers/java/src/main/java/nl/eduvpn/common/InvalidSignatureException.java new file mode 100644 index 0000000..e531206 --- /dev/null +++ b/wrappers/java/src/main/java/nl/eduvpn/common/InvalidSignatureException.java @@ -0,0 +1,8 @@ +package nl.eduvpn.common; + +/** Signature is invalid (for the expected file type). */ +public final class InvalidSignatureException extends VerifyException { + public InvalidSignatureException() { + super("invalid signature"); + } +} diff --git a/wrappers/java/src/main/java/nl/eduvpn/common/InvalidSignatureUnknownKeyException.java b/wrappers/java/src/main/java/nl/eduvpn/common/InvalidSignatureUnknownKeyException.java new file mode 100644 index 0000000..8eaf661 --- /dev/null +++ b/wrappers/java/src/main/java/nl/eduvpn/common/InvalidSignatureUnknownKeyException.java @@ -0,0 +1,8 @@ +package nl.eduvpn.common; + +/** Signature was created with an unknown key and has not been verified. */ +public final class InvalidSignatureUnknownKeyException extends VerifyException { + public InvalidSignatureUnknownKeyException() { + super("invalid signature (unknown key)"); + } +} diff --git a/wrappers/java/src/main/java/nl/eduvpn/common/SignatureTooOldException.java b/wrappers/java/src/main/java/nl/eduvpn/common/SignatureTooOldException.java new file mode 100644 index 0000000..c40c718 --- /dev/null +++ b/wrappers/java/src/main/java/nl/eduvpn/common/SignatureTooOldException.java @@ -0,0 +1,8 @@ +package nl.eduvpn.common; + +/** Signature timestamp smaller than specified minimum signing time (rollback). */ +public final class SignatureTooOldException extends VerifyException { + public SignatureTooOldException() { + super("replay of previous signature (rollback)"); + } +} diff --git a/wrappers/java/src/main/java/nl/eduvpn/common/UnknownVerifyException.java b/wrappers/java/src/main/java/nl/eduvpn/common/UnknownVerifyException.java new file mode 100644 index 0000000..fa76a44 --- /dev/null +++ b/wrappers/java/src/main/java/nl/eduvpn/common/UnknownVerifyException.java @@ -0,0 +1,9 @@ +package nl.eduvpn.common; + +/** Other unknown error. */ +public final class UnknownVerifyException extends VerifyException { + public UnknownVerifyException(byte code) { + super(String.format("unknown verify error (%d)", code)); + assert code != 0; + } +} diff --git a/wrappers/java/src/main/java/nl/eduvpn/common/VerifyException.java b/wrappers/java/src/main/java/nl/eduvpn/common/VerifyException.java index 83dffb1..71ea290 100644 --- a/wrappers/java/src/main/java/nl/eduvpn/common/VerifyException.java +++ b/wrappers/java/src/main/java/nl/eduvpn/common/VerifyException.java @@ -1,9 +1,8 @@ package nl.eduvpn.common; -public class VerifyException extends Exception { - public final long code; //TODO not use plain long - - public VerifyException(long code) { - this.code = code; +/** Verification failed, do not trust the file. */ +public abstract class VerifyException extends Exception { + protected VerifyException(String message) { + super(message); } -}
\ No newline at end of file +} diff --git a/wrappers/java/src/test/java/nl/eduvpn/common/VerifyTests.java b/wrappers/java/src/test/java/nl/eduvpn/common/VerifyTests.java index b4767a5..a82c019 100644 --- a/wrappers/java/src/test/java/nl/eduvpn/common/VerifyTests.java +++ b/wrappers/java/src/test/java/nl/eduvpn/common/VerifyTests.java @@ -1,6 +1,5 @@ package nl.eduvpn.common; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -18,15 +17,15 @@ class VerifyTests { @SuppressWarnings("OptionalGetWithoutIsPresent") @BeforeAll static void oneTimeSetup() throws IOException { - Discovery.insecureTestingSetExtraKey(Files.lines(testDataDir.resolve("dummy/public.key")).reduce((a, b) -> b).get()); + Discovery.insecureTestingSetExtraKey(Files.lines(testDataDir.resolve("public.key")).reduce((a, b) -> b).get()); } @Test void testValid() { assertDoesNotThrow(() -> Discovery.verify( - Files.readAllBytes(testDataDir.resolve("dummy/server_list.json.minisig")), - Files.readAllBytes(testDataDir.resolve("dummy/server_list.json")), + Files.readAllBytes(testDataDir.resolve("server_list.json.minisig")), + Files.readAllBytes(testDataDir.resolve("server_list.json")), "server_list.json", Instant.EPOCH )); @@ -34,45 +33,45 @@ class VerifyTests { @Test void testInvalidSignature() { - Assertions.assertEquals(2, assertThrows(VerifyException.class, () -> + assertThrows(InvalidSignatureException.class, () -> Discovery.verify( - Files.readAllBytes(testDataDir.resolve("dummy/random.txt")), - Files.readAllBytes(testDataDir.resolve("dummy/server_list.json")), + Files.readAllBytes(testDataDir.resolve("random.txt")), + Files.readAllBytes(testDataDir.resolve("server_list.json")), "server_list.json", Instant.EPOCH - )).code); + )); } @Test void testWrongKey() { - assertEquals(3, assertThrows(VerifyException.class, () -> + assertThrows(InvalidSignatureUnknownKeyException.class, () -> Discovery.verify( - Files.readAllBytes(testDataDir.resolve("dummy/server_list.json.wrong_key.minisig")), - Files.readAllBytes(testDataDir.resolve("dummy/server_list.json")), + Files.readAllBytes(testDataDir.resolve("server_list.json.wrong_key.minisig")), + Files.readAllBytes(testDataDir.resolve("server_list.json")), "server_list.json", Instant.EPOCH - )).code); + )); } @Test void testOldSignature() { - assertEquals(4, assertThrows(VerifyException.class, () -> + assertThrows(SignatureTooOldException.class, () -> Discovery.verify( - Files.readAllBytes(testDataDir.resolve("dummy/server_list.json.minisig")), - Files.readAllBytes(testDataDir.resolve("dummy/server_list.json")), + Files.readAllBytes(testDataDir.resolve("server_list.json.minisig")), + Files.readAllBytes(testDataDir.resolve("server_list.json")), "server_list.json", Instant.MAX - )).code); + )); } @Test void testUnknownExpectedFile() { assertThrows(IllegalArgumentException.class, () -> Discovery.verify( - Files.readAllBytes(testDataDir.resolve("dummy/other_list.json.minisig")), - Files.readAllBytes(testDataDir.resolve("dummy/other_list.json")), + Files.readAllBytes(testDataDir.resolve("other_list.json.minisig")), + Files.readAllBytes(testDataDir.resolve("other_list.json")), "other_list.json", Instant.EPOCH )); } -}
\ No newline at end of file +} |
