Skip to content

Commit 8e4bf1d

Browse files
chenkinsdkocher
authored andcommitted
Fix uvf spec.version.
1 parent 515341f commit 8e4bf1d

File tree

1 file changed

+32
-6
lines changed
  • cryptomator/src/main/java/ch/cyberduck/core/cryptomator/impl/uvf

1 file changed

+32
-6
lines changed

cryptomator/src/main/java/ch/cyberduck/core/cryptomator/impl/uvf/CryptoVault.java

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,25 @@
5656

5757
import java.nio.charset.StandardCharsets;
5858
import java.text.ParseException;
59+
import java.util.Collections;
5960
import java.util.EnumSet;
6061
import java.util.Objects;
6162
import java.util.regex.Pattern;
6263

64+
import com.fasterxml.jackson.core.JsonProcessingException;
6365
import com.google.auto.service.AutoService;
6466
import com.nimbusds.jose.JOSEException;
6567
import com.nimbusds.jose.JWEObjectJSON;
68+
import com.nimbusds.jose.Payload;
6669
import com.nimbusds.jose.crypto.MultiDecrypter;
70+
import com.nimbusds.jose.jwk.JWK;
6771

6872
@AutoService(Vault.class)
6973
public class CryptoVault extends AbstractVault {
7074
private static final Logger log = LogManager.getLogger(CryptoVault.class);
7175

76+
private static final String UVF_SPEC_VERSION_KEY_PARAM = "uvf.spec.version";
77+
7278
private static final String REGULAR_FILE_EXTENSION = ".uvf";
7379
private static final String FILENAME_DIRECTORYID = "dir";
7480
private static final String DIRECTORY_METADATA_FILENAME = String.format("%s%s", FILENAME_DIRECTORYID, REGULAR_FILE_EXTENSION);
@@ -128,20 +134,40 @@ public AbstractVault create(final Session<?> session, final String region, final
128134
return this;
129135
}
130136

137+
public static String decryptWithJWK(final String jwe, final JWK jwk) throws ParseException, JOSEException, JsonProcessingException, VaultException {
138+
final JWEObjectJSON jweObject = JWEObjectJSON.parse(jwe);
139+
jweObject.decrypt(new MultiDecrypter(jwk, Collections.singleton(UVF_SPEC_VERSION_KEY_PARAM)));
140+
141+
// https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.11
142+
// Recipients MAY consider the JWS to be invalid if the critical
143+
// list contains any Header Parameter names defined by this
144+
// specification or [JWA] for use with JWS or if any other constraints on its use are violated.
145+
final Object uvfSpecVersion = jweObject.getHeader().getCustomParams().get(UVF_SPEC_VERSION_KEY_PARAM);
146+
if(uvfSpecVersion.equals(1)) {
147+
throw new VaultException(String.format("Unexpected value for critical header %s: found %s, expected \"1\"", UVF_SPEC_VERSION_KEY_PARAM, uvfSpecVersion));
148+
}
149+
150+
final Payload payload = jweObject.getPayload();
151+
return payload.toString();
152+
}
153+
154+
131155
// load -> unlock -> open
132156
@Override
133157
public CryptoVault load(final Session<?> session, final PasswordCallback callback, final VaultMetadataProvider metadata) throws BackgroundException {
134-
final JWKCallback jwk = JWKCallback.cast(callback);
158+
final JWKCallback jwkCallback = JWKCallback.cast(callback);
135159
final VaultMetadataUVFProvider metadataProvider = VaultMetadataUVFProvider.cast(metadata);
136-
final JWEObjectJSON jweObject;
160+
final String uvfMetadata;
137161
try {
138-
jweObject = JWEObjectJSON.parse(new String(metadataProvider.getMetadata(), StandardCharsets.US_ASCII));
139-
jweObject.decrypt(new MultiDecrypter(jwk.prompt(session.getHost(), StringUtils.EMPTY, StringUtils.EMPTY, new LoginOptions()).getKey()));
162+
final String jwe = new String(metadataProvider.getMetadata(), StandardCharsets.US_ASCII);
163+
final JWK jwk = jwkCallback.prompt(session.getHost(), StringUtils.EMPTY, StringUtils.EMPTY, new LoginOptions()).getKey();
164+
uvfMetadata = decryptWithJWK(jwe, jwk);
140165
}
141-
catch(ParseException | JOSEException e) {
166+
catch(ParseException | JOSEException | JsonProcessingException e) {
142167
throw new VaultException("Failure retrieving key material", e);
143168
}
144-
masterKey = UVFMasterkey.fromDecryptedPayload(jweObject.getPayload().toString());
169+
170+
masterKey = UVFMasterkey.fromDecryptedPayload(uvfMetadata);
145171
final CryptorProvider provider = CryptorProvider.forScheme(CryptorProvider.Scheme.UVF_DRAFT);
146172
log.debug("Initialized crypto provider {}", provider);
147173
this.cryptor = provider.provide(masterKey, FastSecureRandomProvider.get().provide());

0 commit comments

Comments
 (0)