Skip to content

Commit d1d56f2

Browse files
committed
Merge branch 'release/2.0.3'
2 parents dee93fd + b124671 commit d1d56f2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1807
-196
lines changed

.github/workflows/build.yml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ jobs:
88
if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
99
steps:
1010
- uses: actions/checkout@v2
11+
with:
12+
fetch-depth: 0
1113
- uses: actions/setup-java@v1
1214
with:
1315
java-version: 11
@@ -17,12 +19,28 @@ jobs:
1719
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
1820
restore-keys: |
1921
${{ runner.os }}-maven-
22+
- name: Cache SonarCloud packages
23+
uses: actions/cache@v2
24+
with:
25+
path: ~/.sonar/cache
26+
key: ${{ runner.os }}-sonar
27+
restore-keys: ${{ runner.os }}-sonar
2028
- name: Ensure to use tagged version
2129
if: startsWith(github.ref, 'refs/tags/')
2230
run: mvn versions:set --file ./pom.xml -DnewVersion=${GITHUB_REF##*/}
2331
- name: Build and Test
2432
id: buildAndTest
25-
run: mvn -B clean install jacoco:report -Pcoverage,dependency-check
33+
run: >
34+
mvn -B verify
35+
jacoco:report
36+
org.sonarsource.scanner.maven:sonar-maven-plugin:sonar
37+
-Pcoverage,dependency-check
38+
-Dsonar.projectKey=cryptomator_cryptolib
39+
-Dsonar.organization=cryptomator
40+
-Dsonar.host.url=https://sonarcloud.io
41+
env:
42+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
43+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
2644
- name: Upload code coverage report
2745
id: codacyCoverageReporter
2846
run: bash <(curl -Ls https://coverage.codacy.com/get.sh)

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[![Build](https://github.com/cryptomator/cryptolib/workflows/Build/badge.svg)](https://github.com/cryptomator/cryptolib/actions?query=workflow%3ABuild)
2-
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/9d736fe3e9e14dfb8a65949abbe8f712)](https://www.codacy.com/gh/cryptomator/cryptolib/dashboard)
3-
[![Codacy Badge](https://api.codacy.com/project/badge/Coverage/9d736fe3e9e14dfb8a65949abbe8f712)](https://www.codacy.com/gh/cryptomator/cryptolib/dashboard)
4-
[![Known Vulnerabilities](https://snyk.io/test/github/cryptomator/cryptolib/badge.svg)](https://snyk.io/test/github/cryptomator/cryptolib)
2+
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=cryptomator_cryptolib&metric=alert_status)](https://sonarcloud.io/dashboard?id=cryptomator_cryptolib)
3+
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=cryptomator_cryptolib&metric=coverage)](https://sonarcloud.io/dashboard?id=cryptomator_cryptolib)
4+
[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=cryptomator_cryptolib&metric=vulnerabilities)](https://sonarcloud.io/dashboard?id=cryptomator_cryptolib)
55
[![Maven Central](https://img.shields.io/maven-central/v/org.cryptomator/cryptolib.svg?maxAge=86400)](https://repo1.maven.org/maven2/org/cryptomator/cryptolib/)
66
[![Javadocs](http://www.javadoc.io/badge/org.cryptomator/cryptolib.svg)](http://www.javadoc.io/doc/org.cryptomator/cryptolib)
77

pom.xml

Lines changed: 82 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<modelVersion>4.0.0</modelVersion>
33
<groupId>org.cryptomator</groupId>
44
<artifactId>cryptolib</artifactId>
5-
<version>2.0.2</version>
5+
<version>2.0.3</version>
66
<name>Cryptomator Crypto Library</name>
77
<description>This library contains all cryptographic functions that are used by Cryptomator.</description>
88
<url>https://github.com/cryptomator/cryptolib</url>
@@ -18,9 +18,10 @@
1818
<maven.compiler.release>8</maven.compiler.release>
1919

2020
<!-- dependencies -->
21-
<gson.version>2.8.7</gson.version>
21+
<gson.version>2.8.9</gson.version>
2222
<guava.version>30.1.1-jre</guava.version>
2323
<siv-mode.version>1.4.3</siv-mode.version>
24+
<bouncycastle.version>1.69</bouncycastle.version>
2425
<slf4j.version>1.7.31</slf4j.version>
2526

2627
<!-- test dependencies -->
@@ -60,6 +61,14 @@
6061
<version>${siv-mode.version}</version>
6162
</dependency>
6263

64+
<dependency>
65+
<groupId>org.bouncycastle</groupId>
66+
<artifactId>bcpkix-jdk15on</artifactId>
67+
<version>${bouncycastle.version}</version>
68+
<!-- see maven-shade-plugin; we don't want this as a transitive dependency in other projects -->
69+
<optional>true</optional>
70+
</dependency>
71+
6372
<dependency>
6473
<groupId>com.google.code.gson</groupId>
6574
<artifactId>gson</artifactId>
@@ -147,19 +156,81 @@
147156
<encoding>UTF-8</encoding>
148157
<showWarnings>true</showWarnings>
149158
</configuration>
159+
</plugin>
160+
<plugin>
161+
<artifactId>maven-shade-plugin</artifactId>
162+
<version>3.2.4</version>
150163
<executions>
151164
<execution>
152-
<id>java9</id>
153-
<phase>compile</phase>
165+
<phase>package</phase>
154166
<goals>
155-
<goal>compile</goal>
167+
<goal>shade</goal>
156168
</goals>
157169
<configuration>
158-
<release>9</release>
159-
<compileSourceRoots>
160-
<compileSourceRoot>${project.basedir}/src/main/java9</compileSourceRoot>
161-
</compileSourceRoots>
162-
<multiReleaseOutput>true</multiReleaseOutput>
170+
<minimizeJar>true</minimizeJar>
171+
<keepDependenciesWithProvidedScope>false</keepDependenciesWithProvidedScope>
172+
<createDependencyReducedPom>false</createDependencyReducedPom>
173+
<createSourcesJar>false</createSourcesJar>
174+
<artifactSet>
175+
<includes>
176+
<include>org.bouncycastle:*</include>
177+
</includes>
178+
</artifactSet>
179+
<relocations>
180+
<relocation>
181+
<pattern>org.bouncycastle</pattern>
182+
<shadedPattern>org.cryptomator.cryptolib.org.bouncycastle</shadedPattern>
183+
</relocation>
184+
</relocations>
185+
<filters>
186+
<filter>
187+
<artifact>org.bouncycastle:*</artifact>
188+
<excludes>
189+
<exclude>META-INF/**</exclude>
190+
</excludes>
191+
</filter>
192+
</filters>
193+
</configuration>
194+
</execution>
195+
</executions>
196+
</plugin>
197+
<plugin>
198+
<groupId>org.moditect</groupId>
199+
<artifactId>moditect-maven-plugin</artifactId>
200+
<version>1.0.0.RC1</version>
201+
<executions>
202+
<execution>
203+
<id>add-module-infos</id>
204+
<phase>package</phase>
205+
<goals>
206+
<goal>add-module-info</goal>
207+
</goals>
208+
<configuration>
209+
<jvmVersion>9</jvmVersion>
210+
<overwriteExistingFiles>true</overwriteExistingFiles>
211+
<module>
212+
<moduleInfoSource>
213+
module org.cryptomator.cryptolib {
214+
requires org.cryptomator.siv;
215+
requires com.google.gson;
216+
requires com.google.common;
217+
requires org.slf4j;
218+
219+
exports org.cryptomator.cryptolib.api;
220+
exports org.cryptomator.cryptolib.common;
221+
222+
opens org.cryptomator.cryptolib.common to com.google.gson;
223+
224+
uses org.cryptomator.cryptolib.api.CryptorProvider;
225+
226+
provides org.cryptomator.cryptolib.api.CryptorProvider
227+
with org.cryptomator.cryptolib.v1.CryptorProviderImpl, org.cryptomator.cryptolib.v2.CryptorProviderImpl;
228+
}
229+
</moduleInfoSource>
230+
</module>
231+
<jdepsExtraArgs>
232+
<arg>--multi-release=9</arg>
233+
</jdepsExtraArgs>
163234
</configuration>
164235
</execution>
165236
</executions>
@@ -336,7 +407,7 @@
336407
<extensions>true</extensions>
337408
<configuration>
338409
<serverId>ossrh</serverId>
339-
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
410+
<nexusUrl>https://s01.oss.sonatype.org</nexusUrl>
340411
<autoReleaseAfterClose>true</autoReleaseAfterClose>
341412
</configuration>
342413
</plugin>

src/main/java/org/cryptomator/cryptolib/common/DecryptingReadableByteChannel.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import org.cryptomator.cryptolib.api.AuthenticationFailedException;
1212
import org.cryptomator.cryptolib.api.Cryptor;
1313
import org.cryptomator.cryptolib.api.FileHeader;
14-
import org.cryptomator.cryptolib.common.ByteBuffers;
1514

1615
import java.io.EOFException;
1716
import java.io.IOException;

src/main/java/org/cryptomator/cryptolib/common/DestroyableSecretKey.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
*/
3030
public class DestroyableSecretKey implements SecretKey, AutoCloseable {
3131

32-
private transient final byte[] key;
32+
private final transient byte[] key;
3333
private final String algorithm;
3434
private boolean destroyed;
3535

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package org.cryptomator.cryptolib.common;
2+
3+
import com.google.common.base.Preconditions;
4+
5+
import javax.security.auth.Destroyable;
6+
import java.security.KeyPair;
7+
import java.security.MessageDigest;
8+
import java.security.interfaces.ECPrivateKey;
9+
import java.security.interfaces.ECPublicKey;
10+
import java.util.Arrays;
11+
import java.util.Objects;
12+
13+
public class ECKeyPair implements Destroyable {
14+
15+
private final KeyPair keyPair;
16+
private boolean destroyed;
17+
18+
ECKeyPair(KeyPair keyPair) {
19+
Preconditions.checkArgument(keyPair.getPrivate() instanceof ECPrivateKey);
20+
Preconditions.checkArgument(keyPair.getPublic() instanceof ECPublicKey);
21+
this.keyPair = keyPair;
22+
}
23+
24+
public KeyPair keyPair() {
25+
return keyPair;
26+
}
27+
28+
public ECPrivateKey getPrivate() {
29+
Preconditions.checkState(!destroyed);
30+
assert keyPair.getPrivate() instanceof ECPrivateKey;
31+
return (ECPrivateKey) keyPair.getPrivate();
32+
}
33+
34+
public ECPublicKey getPublic() {
35+
Preconditions.checkState(!destroyed);
36+
assert keyPair.getPublic() instanceof ECPublicKey;
37+
return (ECPublicKey) keyPair.getPublic();
38+
}
39+
40+
@Override
41+
public boolean isDestroyed() {
42+
return destroyed;
43+
}
44+
45+
@Override
46+
public void destroy() {
47+
Destroyables.destroySilently(keyPair.getPrivate());
48+
destroyed = true;
49+
}
50+
51+
@Override
52+
public boolean equals(Object o) {
53+
if (this == o) return true;
54+
if (o == null || getClass() != o.getClass()) return false;
55+
ECKeyPair that = (ECKeyPair) o;
56+
return MessageDigest.isEqual(this.getPublic().getEncoded(), that.getPublic().getEncoded());
57+
}
58+
59+
@Override
60+
public int hashCode() {
61+
int result = Objects.hash(keyPair.getPublic().getAlgorithm());
62+
result = 31 * result + Arrays.hashCode(keyPair.getPublic().getEncoded());
63+
return result;
64+
}
65+
}

src/main/java/org/cryptomator/cryptolib/common/EncryptingReadableByteChannel.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import org.cryptomator.cryptolib.api.Cryptor;
44
import org.cryptomator.cryptolib.api.FileHeader;
5-
import org.cryptomator.cryptolib.common.ByteBuffers;
65

76
import java.io.IOException;
87
import java.nio.ByteBuffer;

src/main/java/org/cryptomator/cryptolib/common/EncryptingWritableByteChannel.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@
88
*******************************************************************************/
99
package org.cryptomator.cryptolib.common;
1010

11+
import org.cryptomator.cryptolib.api.Cryptor;
12+
import org.cryptomator.cryptolib.api.FileHeader;
13+
1114
import java.io.IOException;
1215
import java.nio.ByteBuffer;
1316
import java.nio.channels.WritableByteChannel;
1417

15-
import org.cryptomator.cryptolib.api.Cryptor;
16-
import org.cryptomator.cryptolib.api.FileHeader;
17-
import org.cryptomator.cryptolib.common.ByteBuffers;
18-
1918
public class EncryptingWritableByteChannel implements WritableByteChannel {
2019

2120
private final WritableByteChannel delegate;
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package org.cryptomator.cryptolib.common;
2+
3+
import com.google.common.io.BaseEncoding;
4+
import org.cryptomator.cryptolib.api.Masterkey;
5+
import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
6+
import org.cryptomator.cryptolib.ecies.EncryptedMessage;
7+
import org.cryptomator.cryptolib.ecies.ECIntegratedEncryptionScheme;
8+
9+
import javax.crypto.AEADBadTagException;
10+
import java.security.KeyFactory;
11+
import java.security.NoSuchAlgorithmException;
12+
import java.security.PublicKey;
13+
import java.security.interfaces.ECPrivateKey;
14+
import java.security.interfaces.ECPublicKey;
15+
import java.security.spec.InvalidKeySpecException;
16+
import java.security.spec.X509EncodedKeySpec;
17+
import java.util.Arrays;
18+
19+
public class MasterkeyHubAccess {
20+
21+
private static final BaseEncoding BASE64_URL = BaseEncoding.base64Url().omitPadding();
22+
23+
private MasterkeyHubAccess() {
24+
}
25+
26+
/**
27+
* Decrypts a masterkey retrieved from Cryptomator Hub
28+
*
29+
* @param devicePrivateKey Private key of the device this ciphertext is intended for
30+
* @param encodedCiphertext The encrypted masterkey
31+
* @param encodedEphPubKey The ephemeral public key to be used to derive a secret shared between message sender and this device
32+
* @return The decrypted masterkey
33+
* @throws MasterkeyLoadingFailedException If the parameters don't match and decryption fails
34+
*/
35+
public static Masterkey decryptMasterkey(ECPrivateKey devicePrivateKey, String encodedCiphertext, String encodedEphPubKey) throws MasterkeyLoadingFailedException {
36+
byte[] cleartext = new byte[0];
37+
try {
38+
EncryptedMessage message = decode(encodedCiphertext, encodedEphPubKey);
39+
cleartext = ECIntegratedEncryptionScheme.HUB.decrypt(devicePrivateKey, message);
40+
return new Masterkey(cleartext);
41+
} catch (IllegalArgumentException | AEADBadTagException e) {
42+
throw new MasterkeyLoadingFailedException("Key and ciphertext don't match", e);
43+
} finally {
44+
Arrays.fill(cleartext, (byte) 0x00);
45+
}
46+
}
47+
48+
private static EncryptedMessage decode(String encodedCiphertext, String encodedEphPubKey) throws IllegalArgumentException {
49+
byte[] ciphertext = BASE64_URL.decode(encodedCiphertext);
50+
byte[] keyBytes = BASE64_URL.decode(encodedEphPubKey);
51+
try {
52+
PublicKey key = KeyFactory.getInstance("EC").generatePublic(new X509EncodedKeySpec(keyBytes));
53+
if (key instanceof ECPublicKey) {
54+
return new EncryptedMessage((ECPublicKey) key, ciphertext);
55+
} else {
56+
throw new IllegalArgumentException("Key not an EC public key.");
57+
}
58+
} catch (InvalidKeySpecException e) {
59+
throw new IllegalArgumentException("Invalid license public key", e);
60+
} catch (NoSuchAlgorithmException e) {
61+
throw new IllegalStateException(e);
62+
}
63+
}
64+
65+
}

src/main/java/org/cryptomator/cryptolib/common/MessageDigestSupplier.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
public final class MessageDigestSupplier {
1515

1616
public static final MessageDigestSupplier SHA1 = new MessageDigestSupplier("SHA-1");
17+
public static final MessageDigestSupplier SHA256 = new MessageDigestSupplier("SHA-256");
1718

1819
private final String digestAlgorithm;
1920
private final ThreadLocal<MessageDigest> threadLocal;

0 commit comments

Comments
 (0)