Skip to content

Commit 493e5cb

Browse files
committed
just saving
1 parent f1a3244 commit 493e5cb

File tree

7 files changed

+152
-64
lines changed

7 files changed

+152
-64
lines changed

sdk/src/main/java/io/opentdf/platform/sdk/AesGcm.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,9 @@ public byte[] encrypt(byte[] iv, int authTagLen, byte[] plaintext, int offset, i
152152
System.arraycopy(iv, 0, cipherTextWithNonce, 0, iv.length);
153153
System.arraycopy(cipherText, 0, cipherTextWithNonce, iv.length, cipherText.length);
154154
return cipherTextWithNonce;
155-
} catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
156-
throw new RuntimeException("error gcm decrypt", e);
157-
} catch (InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
158-
throw new RuntimeException("error gcm decrypt", e);
155+
} catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException |
156+
InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
157+
throw new RuntimeException("error gcm encrypt", e);
159158
}
160159
}
161160

sdk/src/main/java/io/opentdf/platform/sdk/Autoconfigure.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -910,14 +910,7 @@ static void storeKeysToCache(List<KeyAccessServer> kases, List<SimpleKasKey> kas
910910
}
911911

912912
static String algProto2String(Algorithm e) {
913-
switch (e) {
914-
case ALGORITHM_EC_P521:
915-
return "ec:p521";
916-
case ALGORITHM_RSA_2048:
917-
return "rsa:2048";
918-
default:
919-
throw new IllegalArgumentException("Unknown algorithm: " + e);
920-
}
913+
return KeyType.fromAlgorithm(e).getCurveName();
921914
}
922915

923916
static String algProto2String(KasPublicKeyAlgEnum e) {

sdk/src/main/java/io/opentdf/platform/sdk/ECCMode.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.opentdf.platform.sdk;
22

3+
import java.util.Objects;
4+
35
public class ECCMode {
46
private ECCModeStruct data;
57

@@ -115,6 +117,18 @@ public static int getECCompressedPubKeySize(NanoTDFType.ECCurve curve) {
115117
}
116118
}
117119

120+
@Override
121+
public boolean equals(Object o) {
122+
if (o == null || getClass() != o.getClass()) return false;
123+
ECCMode eccMode = (ECCMode) o;
124+
return Objects.equals(data, eccMode.data);
125+
}
126+
127+
@Override
128+
public int hashCode() {
129+
return Objects.hashCode(data);
130+
}
131+
118132
private class ECCModeStruct {
119133
int curveMode;
120134
int unused;

sdk/src/main/java/io/opentdf/platform/sdk/ECKeyPair.java

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -197,18 +197,12 @@ public static byte[] compressECPublickey(String pemECPubKey) {
197197
PemObject pemObject = pemReader.readPemObject();
198198
PublicKey pubKey = ecKeyFac.generatePublic(new X509EncodedKeySpec(pemObject.getContent()));
199199
return ((ECPublicKey) pubKey).getQ().getEncoded(true);
200-
} catch (NoSuchAlgorithmException e) {
201-
throw new RuntimeException(e);
202-
} catch (IOException e) {
203-
throw new RuntimeException(e);
204-
} catch (InvalidKeySpecException e) {
205-
throw new RuntimeException(e);
206-
} catch (NoSuchProviderException e) {
200+
} catch (NoSuchAlgorithmException | IOException | InvalidKeySpecException | NoSuchProviderException e) {
207201
throw new RuntimeException(e);
208202
}
209203
}
210204

211-
public static String publicKeyFromECPoint(byte[] ecPoint, String curveName) {
205+
public static String publicKeyFromECPoint(byte[] ecPoint, String curveName) throws RuntimeException {
212206
try {
213207
// Create EC Public key
214208
ECNamedCurveParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(curveName);
@@ -274,7 +268,7 @@ public static byte[] computeECDHKey(ECPublicKey publicKey, ECPrivateKey privateK
274268
}
275269

276270
public static byte[] calculateHKDF(byte[] salt, byte[] secret) {
277-
byte[] key = new byte[secret.length];
271+
byte[] key = new byte[32];
278272
HKDFParameters params = new HKDFParameters(secret, salt, null);
279273

280274
HKDFBytesGenerator hkdf = new HKDFBytesGenerator(SHA256Digest.newInstance());

sdk/src/main/java/io/opentdf/platform/sdk/KeyType.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package io.opentdf.platform.sdk;
22

3+
import io.opentdf.platform.policy.Algorithm;
4+
5+
import java.util.Set;
6+
37
public enum KeyType {
48
RSA2048Key("rsa:2048"),
59
EC256Key("ec:secp256r1"),
@@ -39,7 +43,24 @@ public static KeyType fromString(String keyType) {
3943
throw new IllegalArgumentException("No enum constant for key type: " + keyType);
4044
}
4145

46+
public static KeyType fromAlgorithm(Algorithm a) {
47+
switch (a) {
48+
case ALGORITHM_RSA_2048:
49+
return RSA2048Key;
50+
case ALGORITHM_EC_P256:
51+
return EC256Key;
52+
case ALGORITHM_EC_P384:
53+
return EC384Key;
54+
case ALGORITHM_EC_P521:
55+
return EC521Key;
56+
default:
57+
throw new IllegalArgumentException("Unsupported algorithm: " + a);
58+
}
59+
}
60+
61+
private static final Set<KeyType> EC_KEY_TYPES = Set.of(EC256Key, EC384Key, EC521Key);
62+
4263
public boolean isEc() {
43-
return this != RSA2048Key;
64+
return EC_KEY_TYPES.contains(this);
4465
}
4566
}

sdk/src/main/java/io/opentdf/platform/sdk/NanoTDF.java

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import com.google.gson.Gson;
1717
import com.google.gson.GsonBuilder;
1818

19+
import io.opentdf.platform.wellknownconfiguration.WellKnownServiceClientInterface;
20+
import org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi;
1921
import org.bouncycastle.jce.interfaces.ECPublicKey;
2022
import org.slf4j.Logger;
2123
import org.slf4j.LoggerFactory;
@@ -65,6 +67,17 @@ public InvalidNanoTDFConfig(String errorMessage) {
6567
}
6668
}
6769

70+
private static Optional<Config.KASInfo> getBaseKey(WellKnownServiceClientInterface wellKnownService) {
71+
var key = Planner.fetchBaseKey(wellKnownService);
72+
key.ifPresent(k -> {
73+
if (!KeyType.fromAlgorithm(k.getPublicKey().getAlgorithm()).isEc()) {
74+
throw new SDKException(String.format("base key is not an EC key, cannot create NanoTDF using a key of type %s",
75+
k.getPublicKey().getAlgorithm()));
76+
}
77+
});
78+
return key.map(Config.KASInfo::fromSimpleKasKey);
79+
}
80+
6881
private Config.HeaderInfo getHeaderInfo(Config.NanoTDFConfig nanoTDFConfig) throws InvalidNanoTDFConfig, UnsupportedNanoTDFFeature {
6982
if (nanoTDFConfig.collectionConfig.useCollection) {
7083
Config.HeaderInfo headerInfo = nanoTDFConfig.collectionConfig.getHeaderInfo();
@@ -74,22 +87,19 @@ private Config.HeaderInfo getHeaderInfo(Config.NanoTDFConfig nanoTDFConfig) thro
7487
}
7588

7689
Gson gson = new GsonBuilder().create();
77-
if (nanoTDFConfig.kasInfoList.isEmpty()) {
78-
throw new InvalidNanoTDFConfig("kas url is missing");
79-
}
90+
Optional<Config.KASInfo> maybeKas = getKasInfo(nanoTDFConfig).or(() -> NanoTDF.getBaseKey(services.wellknown()));
8091

81-
Config.KASInfo kasInfo = nanoTDFConfig.kasInfoList.get(0);
82-
String url = kasInfo.URL;
83-
if (kasInfo.PublicKey == null || kasInfo.PublicKey.isEmpty()) {
84-
logger.info("no public key provided for KAS at {}, retrieving", url);
85-
kasInfo = services.kas().getECPublicKey(kasInfo, nanoTDFConfig.eccMode.getEllipticCurveType());
92+
if (maybeKas.isEmpty()) {
93+
throw new SDKException("no KAS info provided and couldn't get base key, cannot create NanoTDF");
8694
}
8795

96+
var kasInfo = maybeKas.get();
97+
8898
// Kas url resource locator
89-
ResourceLocator kasURL = new ResourceLocator(nanoTDFConfig.kasInfoList.get(0).URL, kasInfo.KID);
99+
ResourceLocator kasURL = new ResourceLocator(kasInfo.URL, kasInfo.KID);
90100
assert kasURL.getIdentifier() != null : "Identifier in ResourceLocator cannot be null";
91101

92-
ECKeyPair keyPair = new ECKeyPair(nanoTDFConfig.eccMode.getCurveName(), ECKeyPair.ECAlgorithm.ECDSA);
102+
ECKeyPair keyPair = new ECKeyPair(kasInfo.Algorithm, ECKeyPair.ECAlgorithm.ECDSA);
93103

94104
// Generate symmetric key
95105
ECPublicKey kasPublicKey = ECKeyPair.publicKeyFromPem(kasInfo.PublicKey);
@@ -138,7 +148,12 @@ private Config.HeaderInfo getHeaderInfo(Config.NanoTDFConfig nanoTDFConfig) thro
138148
// Create header
139149
byte[] compressedPubKey = keyPair.compressECPublickey();
140150
Header header = new Header();
141-
header.setECCMode(nanoTDFConfig.eccMode);
151+
var mode = new ECCMode();
152+
mode.setEllipticCurve(Enum.valueOf(NanoTDFType.ECCurve.class, keyPair.curveName()));
153+
if (logger.isWarnEnabled() && !nanoTDFConfig.eccMode.equals(mode)) {
154+
logger.warn("ECC mode provided in NanoTDFConfig: {}, ECC mode from key: {}", nanoTDFConfig.eccMode, mode);
155+
}
156+
header.setECCMode(mode);
142157
header.setPayloadConfig(nanoTDFConfig.config);
143158
header.setEphemeralKey(compressedPubKey);
144159
header.setKasLocator(kasURL);
@@ -152,6 +167,21 @@ private Config.HeaderInfo getHeaderInfo(Config.NanoTDFConfig nanoTDFConfig) thro
152167
return headerInfo;
153168
}
154169

170+
private Optional<Config.KASInfo> getKasInfo(Config.NanoTDFConfig nanoTDFConfig) {
171+
if (nanoTDFConfig.kasInfoList.isEmpty()) {
172+
logger.debug("no kas info provided in NanoTDFConfig");
173+
return Optional.empty();
174+
}
175+
176+
Config.KASInfo kasInfo = nanoTDFConfig.kasInfoList.get(0);
177+
String url = kasInfo.URL;
178+
if (kasInfo.PublicKey == null || kasInfo.PublicKey.isEmpty()) {
179+
logger.info("no public key provided for KAS at {}, retrieving", url);
180+
kasInfo = services.kas().getECPublicKey(kasInfo, nanoTDFConfig.eccMode.getEllipticCurveType());
181+
}
182+
return Optional.of(kasInfo);
183+
}
184+
155185
public int createNanoTDF(ByteBuffer data, OutputStream outputStream,
156186
Config.NanoTDFConfig nanoTDFConfig) throws SDKException, IOException {
157187
int nanoTDFSize = 0;

0 commit comments

Comments
 (0)