Skip to content

Commit

Permalink
Merge branch 'master' into lun-UID2-1426-gcp-oidc-attestation-client
Browse files Browse the repository at this point in the history
  • Loading branch information
lunwang-ttd authored Jul 21, 2023
2 parents 61e7f85 + f6b82fa commit 7e26111
Show file tree
Hide file tree
Showing 19 changed files with 129 additions and 87 deletions.
13 changes: 13 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<groupId>com.uid2</groupId>
<artifactId>uid2-shared</artifactId>
<version>2.12.2-SNAPSHOT</version>
<version>2.12.3-7a057c4834</version>

<name>${project.groupId}:${project.artifactId}</name>
<description>Library for all the shared uid2 operations</description>
Expand Down Expand Up @@ -189,6 +190,18 @@
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/com/uid2/shared/auth/Keyset.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.fasterxml.jackson.annotation.JsonProperty;

import java.time.Instant;
import java.util.Arrays;
import java.util.Objects;
import java.util.Set;
Expand Down Expand Up @@ -79,7 +78,7 @@ public boolean equals(Object o) {
&& this.isEnabled == b.isEnabled
&& this.isDefault == b.isDefault;

if(this.allowedSites == null || this.allowedSites == null) {
if(this.allowedSites == null || b.allowedSites == null) {
return compare && this.allowedSites == b.allowedSites;
}

Expand Down
19 changes: 12 additions & 7 deletions src/main/java/com/uid2/shared/auth/KeysetSnapshot.java
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
package com.uid2.shared.auth;

import com.uid2.shared.model.KeysetKey;
import com.uid2.shared.store.IKeysetSnapshot;
import com.uid2.shared.store.ACLMode.MissingAclMode;

import java.util.Map;

public class KeysetSnapshot implements IKeysetSnapshot {
public class KeysetSnapshot {
private final Map<Integer, Keyset> keysets;

public KeysetSnapshot(Map<Integer, Keyset> keysets) { this.keysets = keysets; }
@Override
public boolean canClientAccessKey(ClientKey clientKey, KeysetKey key) {

public boolean canClientAccessKey(ClientKey clientKey, KeysetKey key, MissingAclMode accessMethod) {
Keyset keyset = keysets.get(key.getKeysetId());

if(!keyset.isEnabled()) return false;
if (keyset == null || !keyset.isEnabled() || clientKey == null) return false;

if (keyset.getSiteId() == clientKey.getSiteId()) return true;

if(keyset.getSiteId() == clientKey.getSiteId()) return true;
if (accessMethod == MissingAclMode.ALLOW_ALL
&& keyset.getAllowedSites() == null) return true;

return keyset.canBeAccessedBySite(clientKey.getSiteId());
}

public Map<Integer, Keyset> getAllKeysets() { return keysets; }
public Map<Integer, Keyset> getAllKeysets() { return this.keysets; }

public Keyset getKeyset(int keysetId) { return this.keysets.get(keysetId); }
}
8 changes: 4 additions & 4 deletions src/main/java/com/uid2/shared/encryption/AesCbc.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.uid2.shared.encryption;

import com.uid2.shared.model.EncryptedPayload;
import com.uid2.shared.model.EncryptionKey;
import com.uid2.shared.model.KeysetKey;
import io.vertx.core.buffer.Buffer;

import javax.crypto.Cipher;
Expand All @@ -13,7 +13,7 @@
public class AesCbc {
private static final String cipherScheme = "AES/CBC/PKCS5Padding";

public static EncryptedPayload encrypt(byte[] b, EncryptionKey key) {
public static EncryptedPayload encrypt(byte[] b, KeysetKey key) {
try {
final SecretKey k = new SecretKeySpec(key.getKeyBytes(), "AES");
final Cipher c = Cipher.getInstance(cipherScheme);
Expand All @@ -27,15 +27,15 @@ public static EncryptedPayload encrypt(byte[] b, EncryptionKey key) {
}
}

public static EncryptedPayload encrypt(String s, EncryptionKey key) {
public static EncryptedPayload encrypt(String s, KeysetKey key) {
try {
return encrypt(s.getBytes(StandardCharsets.UTF_8), key);
} catch (Exception e) {
throw new RuntimeException("Unable to Encrypt", e);
}
}

public static byte[] decrypt(byte[] encryptedBytes, EncryptionKey key) {
public static byte[] decrypt(byte[] encryptedBytes, KeysetKey key) {
try {
final SecretKey k = new SecretKeySpec(key.getKeyBytes(), "AES");
return decrypt(encryptedBytes, k);
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/com/uid2/shared/encryption/AesGcm.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.uid2.shared.encryption;

import com.uid2.shared.model.EncryptedPayload;
import com.uid2.shared.model.EncryptionKey;
import com.uid2.shared.model.KeysetKey;
import io.vertx.core.buffer.Buffer;

import javax.crypto.Cipher;
Expand All @@ -15,7 +15,7 @@ public class AesGcm {
public static final int GCM_AUTHTAG_LENGTH = 16;
public static final int GCM_IV_LENGTH = 12;

public static EncryptedPayload encrypt(byte[] b, EncryptionKey key) {
public static EncryptedPayload encrypt(byte[] b, KeysetKey key) {
try {
byte[] encrypted = encrypt(b, key.getKeyBytes());
return new EncryptedPayload(key.getKeyIdentifier(), encrypted);
Expand All @@ -24,7 +24,7 @@ public static EncryptedPayload encrypt(byte[] b, EncryptionKey key) {
}
}

public static EncryptedPayload encrypt(String s, EncryptionKey key) {
public static EncryptedPayload encrypt(String s, KeysetKey key) {
try {
return encrypt(s.getBytes(StandardCharsets.UTF_8), key);
} catch (Exception e) {
Expand All @@ -45,7 +45,7 @@ public static byte[] encrypt(byte[] b, byte[] secretBytes) {
}
}

public static byte[] decrypt(byte[] encryptedBytes, int offset, EncryptionKey key) {
public static byte[] decrypt(byte[] encryptedBytes, int offset, KeysetKey key) {
try {
return decrypt(encryptedBytes, offset, key.getKeyBytes());
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package com.uid2.shared.secure.gcpoidc;

import com.google.api.client.json.gson.GsonFactory;
import com.google.api.client.json.webtoken.JsonWebSignature;
import com.google.api.client.util.Clock;
import com.google.auth.oauth2.TokenVerifier;
import com.google.common.base.Strings;
import com.uid2.shared.secure.AttestationException;

import java.io.IOException;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class TokenSignatureValidator implements ITokenSignatureValidator{
public class TokenSignatureValidator implements ITokenSignatureValidator {
private static final String PUBLIC_CERT_LOCATION =
"https://www.googleapis.com/service_accounts/v1/metadata/jwk/[email protected]";

Expand All @@ -20,19 +22,22 @@ public class TokenSignatureValidator implements ITokenSignatureValidator{
private static final String ISSUER = "https://confidentialcomputing.googleapis.com";
private final TokenVerifier tokenVerifier;

public TokenSignatureValidator(){
// set to true to facilitate local test with self-signed cert.
public static final boolean BYPASS_SIGNATURE_CHECK = false;

public TokenSignatureValidator() {
this(null, null);
}

protected TokenSignatureValidator(PublicKey publicKeyOverride, Clock clockOverride){
protected TokenSignatureValidator(PublicKey publicKeyOverride, Clock clockOverride) {
var verifierBuilder = TokenVerifier.newBuilder();
verifierBuilder.setCertificatesLocation(PUBLIC_CERT_LOCATION);

if(publicKeyOverride != null){
if (publicKeyOverride != null) {
verifierBuilder.setPublicKey(publicKeyOverride);
}

if(clockOverride != null){
if (clockOverride != null) {
verifierBuilder.setClock(clockOverride);
}

Expand All @@ -50,11 +55,16 @@ public TokenPayload validate(String tokenString) throws AttestationException {

// Validate Signature
JsonWebSignature signature;
try{
signature = tokenVerifier.verify(tokenString);
}
catch (TokenVerifier.VerificationException e){
try {
if (BYPASS_SIGNATURE_CHECK) {
signature = JsonWebSignature.parse(GsonFactory.getDefaultInstance(), tokenString);
} else {
signature = tokenVerifier.verify(tokenString);
}
} catch (TokenVerifier.VerificationException e) {
throw new AttestationException("Fail to validate the token signature, error: " + e.getMessage());
} catch (IOException e) {
throw new AttestationException("Fail to parse token, error: " + e.getMessage());
}

// Parse Payload
Expand Down
8 changes: 0 additions & 8 deletions src/main/java/com/uid2/shared/store/IKeysetSnapshot.java

This file was deleted.

15 changes: 7 additions & 8 deletions src/test/java/com/uid2/shared/encryption/AesCbcTest.java
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
package com.uid2.shared.encryption;

import com.uid2.shared.model.EncryptedPayload;
import com.uid2.shared.model.EncryptionKey;
import com.uid2.shared.model.KeysetKey;
import junit.framework.TestCase;
import org.junit.Assert;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.time.Instant;

public class AesCbcTest extends TestCase {

public void testEncryptionDecryption() throws Exception {

final EncryptionKey key = new EncryptionKey(1, Random.getRandomKeyBytes(), Instant.now(), Instant.now(), Instant.now(), -1);
final KeysetKey key = new KeysetKey(1, Random.getRandomKeyBytes(), Instant.now(), Instant.now(), Instant.now(), 123);
final String testString = "[email protected]";

final EncryptedPayload payload = AesCbc.encrypt(testString, key);
final byte[] decrypted = AesCbc.decrypt(payload.getPayload(), key);

final String decryptedString = new String(decrypted, "UTF-8");
final String decryptedString = new String(decrypted, StandardCharsets.UTF_8);
Assert.assertEquals(testString, decryptedString);
}

public void testDecryption() {
byte[] keyBytes = new byte[]{-82, -66, -67, -114, 87, 24, -108, 82, -77, 112, 9, 80, 118, 39, 66, -35, 59, -81, -72, -81, 30, -41, 113, 101, -76, 79, 119, -73, 59, -39, 0, 75};
byte[] encypted = new byte[]{34, -42, -99, 68, 110, 49, 45, 57, 11, 64, 74, -43, 86, -73, 33, -125, -100, 2, -27, 38, 103, 97, -17, -115, -116, 10, 102, -41, -35, -53, 34, 60, -44, 59, 101, 24, -14, 9, -56, -71, 86, -31, -44, -75, -124, -77, 58, -20, 3, 26, -39, 95, 100, 24, -110, 100, 34, 25, -4, 41, -93, -3, -83, -44, 91, -1, 34, 25, 83, -58, 42, -116, 51, -112, 91, 71, 8, -25, 26, 41};
final EncryptionKey key = new EncryptionKey(1, keyBytes, Instant.now(), Instant.now(), Instant.now(), -1);
byte[] payload = AesCbc.decrypt(encypted, key);
byte[] encrypted = new byte[]{34, -42, -99, 68, 110, 49, 45, 57, 11, 64, 74, -43, 86, -73, 33, -125, -100, 2, -27, 38, 103, 97, -17, -115, -116, 10, 102, -41, -35, -53, 34, 60, -44, 59, 101, 24, -14, 9, -56, -71, 86, -31, -44, -75, -124, -77, 58, -20, 3, 26, -39, 95, 100, 24, -110, 100, 34, 25, -4, 41, -93, -3, -83, -44, 91, -1, 34, 25, 83, -58, 42, -116, 51, -112, 91, 71, 8, -25, 26, 41};
final KeysetKey key = new KeysetKey(1, keyBytes, Instant.now(), Instant.now(), Instant.now(), 123);
byte[] payload = AesCbc.decrypt(encrypted, key);
String expected = "[email protected]";
String results = new String(payload);
assertEquals(results, expected);
Expand Down
10 changes: 4 additions & 6 deletions src/test/java/com/uid2/shared/encryption/AesGcmTest.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
package com.uid2.shared.encryption;

import com.uid2.shared.model.EncryptedPayload;
import com.uid2.shared.model.EncryptionKey;
import com.uid2.shared.model.KeysetKey;
import junit.framework.TestCase;

import java.nio.charset.StandardCharsets;
import java.time.Instant;

import static org.junit.Assert.assertArrayEquals;

public class AesGcmTest extends TestCase {
public void testEncryptionDecryption() {
final EncryptionKey key = new EncryptionKey(1, Random.getRandomKeyBytes(), Instant.now(), Instant.now(), Instant.now(), -1);
final KeysetKey key = new KeysetKey(1, Random.getRandomKeyBytes(), Instant.now(), Instant.now(), Instant.now(), 123);
String plaintxt = "hello world";
EncryptedPayload payload = AesGcm.encrypt(plaintxt.getBytes(StandardCharsets.UTF_8), key);
String decryptedText = new String(AesGcm.decrypt(payload.getPayload(), 0, key), StandardCharsets.UTF_8);
assertEquals(plaintxt, decryptedText);
}

public void testEncryptionDecryptionString() {
final EncryptionKey key = new EncryptionKey(1, Random.getRandomKeyBytes(), Instant.now(), Instant.now(), Instant.now(), -1);
final KeysetKey key = new KeysetKey(1, Random.getRandomKeyBytes(), Instant.now(), Instant.now(), Instant.now(), 123);
String plaintxt = "hello world";
EncryptedPayload payload = AesGcm.encrypt(plaintxt, key);
String decryptedText = new String(AesGcm.decrypt(payload.getPayload(), 0, key), StandardCharsets.UTF_8);
Expand All @@ -29,7 +27,7 @@ public void testEncryptionDecryptionString() {
public void testDecryption() {
byte[] keyBytes = new byte[]{19, -105, -79, 100, 11, 38, -93, 100, 123, 111, 68, -57, 67, -12, -33, 14, -53, -120, -66, -116, 30, 9, -123, -50, -36, 73, 79, 85, 78, -18, 42, -108};
byte[] encypted = new byte[]{-2, 35, -109, -1, -123, 75, 111, 93, 83, 0, -11, -97, -69, -10, 88, 82, -62, 83, 76, -75, -51, 45, 87, 102, 38, 117, 98, 84, -78, -100, -2, -99, -3, -121, 94, 23, 75, 84, 20};
final EncryptionKey key = new EncryptionKey(1, keyBytes, Instant.now(), Instant.now(), Instant.now(), -1);
final KeysetKey key = new KeysetKey(1, keyBytes, Instant.now(), Instant.now(), Instant.now(), 123);
byte[] payload = AesGcm.decrypt(encypted,0, key);
String expected = "hello world";
String results = new String(payload);
Expand Down
6 changes: 3 additions & 3 deletions src/test/java/com/uid2/shared/encryption/BenchmarkTests.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.uid2.shared.encryption;

import com.uid2.shared.model.EncryptedPayload;
import com.uid2.shared.model.EncryptionKey;
import com.uid2.shared.model.KeysetKey;
import junit.framework.TestCase;

import javax.crypto.SecretKey;
Expand All @@ -16,7 +16,7 @@ public void testBenchmarkCbc() throws Exception {
}
System.out.println("Java VM property java.security.egd: " + System.getProperty("java.security.egd"));
final int runs = 1000000;
final EncryptionKey key = new EncryptionKey(1, Random.getRandomKeyBytes(), Instant.now(), Instant.now(), Instant.now(), -1);
final KeysetKey key = new KeysetKey(1, Random.getRandomKeyBytes(), Instant.now(), Instant.now(), Instant.now(), 123);

final EncryptedPayload[] payloads = new EncryptedPayload[runs];

Expand Down Expand Up @@ -57,7 +57,7 @@ public void testBenchmarkGcm() throws Exception {
}
System.out.println("Java VM property java.security.egd: " + System.getProperty("java.security.egd"));
final int runs = 1000000;
final EncryptionKey key = new EncryptionKey(1, Random.getRandomKeyBytes(), Instant.now(), Instant.now(), Instant.now(), -1);
final KeysetKey key = new KeysetKey(1, Random.getRandomKeyBytes(), Instant.now(), Instant.now(), Instant.now(), 123);

final EncryptedPayload[] payloads = new EncryptedPayload[runs];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
import com.uid2.shared.secure.gcpoidc.TokenPayload;
import io.vertx.core.AsyncResult;
import io.vertx.core.Handler;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
Expand All @@ -19,7 +21,8 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class GcpOidcAttestationProviderTest {
private static final String ATTESTATION_REQUEST = "test-attestation-request";
private static final String PUBLIC_KEY = "test-public-key";
Expand All @@ -30,17 +33,22 @@ public class GcpOidcAttestationProviderTest {

private static final TokenPayload VALID_TOKEN_PAYLOAD = TokenPayload.builder().build();

@Mock private ITokenSignatureValidator alwaysPassTokenValidator;
@Mock private ITokenSignatureValidator alwaysFailTokenValidator;
@Mock
private ITokenSignatureValidator alwaysPassTokenValidator;
@Mock
private ITokenSignatureValidator alwaysFailTokenValidator;

@Mock private IPolicyValidator alwaysPassPolicyValidator1;
@Mock
private IPolicyValidator alwaysPassPolicyValidator1;

@Mock private IPolicyValidator alwaysPassPolicyValidator2;
@Mock
private IPolicyValidator alwaysPassPolicyValidator2;

@Mock private IPolicyValidator alwaysFailPolicyValidator;
@Mock
private IPolicyValidator alwaysFailPolicyValidator;


@Before
@BeforeEach
public void setup() throws AttestationException {
when(alwaysPassTokenValidator.validate(any())).thenReturn(VALID_TOKEN_PAYLOAD);
when(alwaysFailTokenValidator.validate(any())).thenThrow(new AttestationException("token signature validation failed"));
Expand Down
Loading

0 comments on commit 7e26111

Please sign in to comment.