Skip to content

Commit

Permalink
resolved merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
purnimavenkatasubbu committed Jan 16, 2024
2 parents 341a0a8 + 8393445 commit 03e9ab0
Show file tree
Hide file tree
Showing 8 changed files with 334 additions and 26 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/scorecards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0
uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0
with:
name: SARIF file
path: results.sarif
Expand Down
9 changes: 8 additions & 1 deletion packages/at_client/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
# 3.0.72
# 3.0.73
- build[deps]: Upgraded dependencies for the following packages:
- at_commons to v4.0.0
- at_utils to v3.0.16
- at_lookup to v3.0.44
- at_chops to v1.0.7
- at_persistence_secondary_server to v3.0.60
## 3.0.72
- chore: Minor change to allow us to support dart
versions both before and after 3.2.0 specifically for this
[Dart breaking change](https://github.com/dart-lang/sdk/issues/52801)
which was
[introduced](https://github.com/dart-lang/sdk/blob/main/CHANGELOG.md)
in dart 3.2.0
## 3.0.71
- feat: Replace decryption methods from EncryptionUtil with AtChops methods
## 3.0.70
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class AtClientConfig {

/// Represents the at_client version.
/// Must always be the same as the actual version in pubspec.yaml
final String atClientVersion = '3.0.72';
final String atClientVersion = '3.0.73';

/// Represents the client commit log compaction time interval
///
Expand Down
5 changes: 4 additions & 1 deletion packages/at_client/lib/src/util/at_client_util.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:convert';
import 'dart:typed_data';

import 'package:at_client/at_client.dart';
import 'package:at_client/src/converters/encoder/at_encoder.dart';
Expand Down Expand Up @@ -33,7 +34,9 @@ class AtClientUtil {
static String signChallenge(String challenge, String privateKey) {
var key = RSAPrivateKey.fromString(privateKey);
challenge = challenge.trim();
var signature = key.createSHA256Signature(utf8.encode(challenge));
var signature =
// ignore: unnecessary_cast
key.createSHA256Signature(utf8.encode(challenge) as Uint8List);
return base64Encode(signature);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/at_client/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: The at_client library is the non-platform specific Client SDK which
##
##
## NB: When incrementing the version, please also increment the version in AtClientConfig file
version: 3.0.72
version: 3.0.73
## NB: When incrementing the version, please also increment the version in AtClientConfig file
##

Expand Down
78 changes: 78 additions & 0 deletions packages/at_client/test/self_key_encryption_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import 'package:at_chops/at_chops.dart';
import 'package:at_client/src/decryption_service/self_key_decryption.dart';
import 'package:at_client/src/encryption_service/self_key_encryption.dart';
import 'package:at_commons/at_builders.dart';
import 'package:test/test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:at_client/at_client.dart';
import 'package:at_lookup/at_lookup.dart';

class MockAtClientImpl extends Mock implements AtClient {}

class MockLocalSecondary extends Mock implements LocalSecondary {}

class MockRemoteSecondary extends Mock implements RemoteSecondary {}

class MockAtLookupImpl extends Mock implements AtLookUp {}

class FakeLocalLookUpVerbBuilder extends Fake implements LLookupVerbBuilder {}

void main() {
AtClient mockAtClient = MockAtClientImpl();
AtLookUp mockAtLookUp = MockAtLookupImpl();
LocalSecondary mockLocalSecondary = MockLocalSecondary();
RemoteSecondary mockRemoteSecondary = MockRemoteSecondary();
setUp(() {
reset(mockAtLookUp);
when(() => mockAtClient.getLocalSecondary())
.thenAnswer((_) => mockLocalSecondary);
when(() => mockAtClient.getRemoteSecondary())
.thenAnswer((_) => mockRemoteSecondary);

registerFallbackValue(FakeLocalLookUpVerbBuilder());
});

test('test to check encryption/decryption of self keys', () async {
// This test encrypts a self key value and then checks whether decrypted value is same as original value
// If @alice wants to maintain a location without sharing to anyone then the key-value format will be @alice:location@alice New Jersey
// @alice uses self encryption AES key generated during onboarding process to encrypt the value. Same key is used for decryption
var selfKeyEncryption = SelfKeyEncryption(mockAtClient);
var selfKeyDecryption = SelfKeyDecryption(mockAtClient);
// generate new AES key for the test
var aliceSelfEncryptionKey =
AtChopsUtil.generateSymmetricKey(EncryptionKeyType.aes256).key;
// set atChops
AtChopsKeys atChopsKeys = AtChopsKeys.create(null, null);
atChopsKeys.selfEncryptionKey = AESKey(aliceSelfEncryptionKey);
var atChopsImpl = AtChopsImpl(atChopsKeys);
when(() => mockAtClient.atChops).thenAnswer((_) => atChopsImpl);
when(() => mockLocalSecondary.getEncryptionSelfKey())
.thenAnswer((_) => Future.value(aliceSelfEncryptionKey));
var selfKey = AtKey()
..sharedBy = '@alice'
..sharedWith = '@bob'
..key = 'location';
var location = 'New Jersey';
var encryptedValue = await selfKeyEncryption.encrypt(selfKey, location);
expect(encryptedValue != location, true);
var decryptionResult =
await selfKeyDecryption.decrypt(selfKey, encryptedValue);
expect(decryptionResult, location);
});
test(
'test to check self key encryption throws exception when passed value is not string type',
() async {
var selfKeyEncryption = SelfKeyEncryption(mockAtClient);
var selfKey = AtKey()
..sharedBy = '@alice'
..sharedWith = '@bob'
..key = 'location';
var locations = ['new jersey', 'new york'];
expect(
() async => await selfKeyEncryption.encrypt(selfKey, locations),
throwsA(predicate((dynamic e) =>
e is AtEncryptionException &&
e.message ==
'Invalid value type found: List<String>. Valid value type is String')));
});
}
220 changes: 220 additions & 0 deletions packages/at_client/test/shared_key_encryption_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
import 'package:at_chops/at_chops.dart';
import 'package:at_client/src/decryption_service/shared_key_decryption.dart';
import 'package:at_client/src/encryption_service/shared_key_encryption.dart';
import 'package:at_commons/at_builders.dart';
import 'package:test/test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:at_client/at_client.dart';
import 'package:at_lookup/at_lookup.dart';

class MockAtClientImpl extends Mock implements AtClient {}

class MockLocalSecondary extends Mock implements LocalSecondary {}

class MockRemoteSecondary extends Mock implements RemoteSecondary {}

class MockAtLookupImpl extends Mock implements AtLookUp {}

class FakeLocalLookUpVerbBuilder extends Fake implements LLookupVerbBuilder {}

class FakeDeleteVerbBuilder extends Fake implements DeleteVerbBuilder {}

void main() {
AtClient mockAtClient = MockAtClientImpl();
AtLookUp mockAtLookUp = MockAtLookupImpl();
LocalSecondary mockLocalSecondary = MockLocalSecondary();
RemoteSecondary mockRemoteSecondary = MockRemoteSecondary();
setUp(() {
reset(mockAtLookUp);
when(() => mockAtClient.getLocalSecondary())
.thenAnswer((_) => mockLocalSecondary);
when(() => mockAtClient.getRemoteSecondary())
.thenAnswer((_) => mockRemoteSecondary);

registerFallbackValue(FakeLocalLookUpVerbBuilder());
registerFallbackValue(FakeDeleteVerbBuilder());
});

test(
'test to verify encryption and decryption of a key shared by @alice with @bob - without IV',
() async {
// This test verifies encryption and decryption of a shared key value without using Initialization vector(IV)
// Value of a shared key is encrypted and then test asserts whether decrypted value is same as original value
// If @alice wants to share location value with bob, then key-value format is @bob:location@alice California
// @alice will generate a AES key and will encrypt the location value - California
// The AES key will be encrypted with @bob's public key and stored in @bob:shared_key@alice
// When @bob wants to decrypt the @alice's location, @bob will read the encrypted AES key from @bob:shared_key@alice
// @bob will decrypt the AES key using @bob's private key
// @bob will decrypt the location value - California with AES key

var sharedKeyEncryption = SharedKeyEncryption(mockAtClient);
var bobMockAtClient = MockAtClientImpl();
var bobMockLocalSecondary = MockLocalSecondary();
// set up encryption key pair for @alice. This will be used during encryption process
var aliceEncryptionKeyPair = AtChopsUtil.generateAtEncryptionKeyPair();
var aliceEncryptionPublicKey = aliceEncryptionKeyPair.atPublicKey.publicKey;
// Set up encryption key pair for @bob. This will be used during decryption process
var bobEncryptionKeyPair = AtChopsUtil.generateAtEncryptionKeyPair();
var bobEncryptionPublicKey = bobEncryptionKeyPair.atPublicKey.publicKey;

// Generate the AES for encrypting the location value
var aesSharedKey =
AtChopsUtil.generateSymmetricKey(EncryptionKeyType.aes256).key;
// set atChops for bob
AtChopsKeys bobAtChopsKeys = AtChopsKeys.create(bobEncryptionKeyPair, null);
var bobAtChopsImpl = AtChopsImpl(bobAtChopsKeys);
when(() => bobMockAtClient.atChops).thenAnswer((_) => bobAtChopsImpl);
when(() => bobMockAtClient.getLocalSecondary())
.thenAnswer((_) => bobMockLocalSecondary);
when(() => bobMockAtClient.getCurrentAtSign()).thenReturn('@bob');
when(() => bobMockLocalSecondary.getEncryptionPublicKey('@bob'))
.thenAnswer((_) => Future.value(bobEncryptionPublicKey));
var sharedKeyDecryption = SharedKeyDecryption(bobMockAtClient);

// encrypted AES key @bob:shared_key@alice
var sharedKeyEncryptedWithBobPublicKey =
EncryptionUtil.encryptKey(aesSharedKey, bobEncryptionPublicKey);

// local copy of the AES key that @alice maintains - shared_key.bob@alice
var sharedKeyEncryptedWithAlicePublicKey =
EncryptionUtil.encryptKey(aesSharedKey, aliceEncryptionPublicKey);

var bobPublicKeyCheckSum =
EncryptionUtil.md5CheckSum(bobEncryptionPublicKey);
var location = 'California';

// set atChops for alice
AtChopsKeys atChopsKeys = AtChopsKeys.create(aliceEncryptionKeyPair, null);
var atChopsImpl = AtChopsImpl(atChopsKeys);
when(() => mockAtClient.atChops).thenAnswer((_) => atChopsImpl);
when(() => mockAtClient.getCurrentAtSign()).thenReturn('@alice');
when(() => mockLocalSecondary.getEncryptionPublicKey('@alice'))
.thenAnswer((_) => Future.value(aliceEncryptionPublicKey));
when(() => mockLocalSecondary.executeVerb(any<LLookupVerbBuilder>()))
.thenAnswer((Invocation invocation) {
final builder = invocation.positionalArguments[0] as LLookupVerbBuilder;
final buildKeyValue = builder.buildKey();
if (buildKeyValue == 'shared_key.bob@alice') {
return Future.value('data:$sharedKeyEncryptedWithAlicePublicKey');
} else if (buildKeyValue == 'cached:public:publickey@bob') {
return Future.value('data:$bobEncryptionPublicKey');
} else if (buildKeyValue == '@bob:shared_key@alice') {
return Future.value('data:$sharedKeyEncryptedWithBobPublicKey');
} else {
return Future.value('data:null');
}
});
var sharedKey = AtKey()
..sharedBy = '@alice'
..sharedWith = '@bob'
..key = 'location';
sharedKey.metadata = (Metadata()..pubKeyCS = bobPublicKeyCheckSum);
var encryptionResult =
await sharedKeyEncryption.encrypt(sharedKey, location);
expect(encryptionResult != location, true);
var decryptionResult =
await sharedKeyDecryption.decrypt(sharedKey, encryptionResult);
expect(decryptionResult, location);
});

test(
'test to verify encryption and decryption of a key shared by @alice with @bob - with IV',
() async {
// This test verifies encryption and decryption of a shared key value by using Initialization vector(IV)
// If @alice wants to share location value with bob, then key-value format is @bob:location@alice California
// @alice will generate a AES key and will encrypt the location value - California
// The AES key will be encrypted with @bob's public key and stored in @bob:shared_key@alice
// When @bob wants to decrypt the @alice's location, @bob will read the encrypted AES key from @bob:shared_key@alice
// @bob will decrypt the AES key using @bob's private key
// @bob will decrypt the location value - California with AES key

var sharedKeyEncryption = SharedKeyEncryption(mockAtClient);
var bobMockAtClient = MockAtClientImpl();
var bobMockLocalSecondary = MockLocalSecondary();
// set up encryption key pair for @alice. This will be used during encryption process
var aliceEncryptionKeyPair = AtChopsUtil.generateAtEncryptionKeyPair();
var aliceEncryptionPublicKey = aliceEncryptionKeyPair.atPublicKey.publicKey;
// Set up encryption key pair for @bob. This will be used during decryption process
var bobEncryptionKeyPair = AtChopsUtil.generateAtEncryptionKeyPair();
var bobEncryptionPublicKey = bobEncryptionKeyPair.atPublicKey.publicKey;

// Generate the AES for encrypting the location value
var aesSharedKey =
AtChopsUtil.generateSymmetricKey(EncryptionKeyType.aes256).key;
// set atChops for bob
AtChopsKeys bobAtChopsKeys = AtChopsKeys.create(bobEncryptionKeyPair, null);
var bobAtChopsImpl = AtChopsImpl(bobAtChopsKeys);
when(() => bobMockAtClient.atChops).thenAnswer((_) => bobAtChopsImpl);
when(() => bobMockAtClient.getLocalSecondary())
.thenAnswer((_) => bobMockLocalSecondary);
when(() => bobMockAtClient.getCurrentAtSign()).thenReturn('@bob');
when(() => bobMockLocalSecondary.getEncryptionPublicKey('@bob'))
.thenAnswer((_) => Future.value(bobEncryptionPublicKey));
var sharedKeyDecryption = SharedKeyDecryption(bobMockAtClient);

// encrypted AES key @bob:shared_key@alice
var sharedKeyEncryptedWithBobPublicKey =
EncryptionUtil.encryptKey(aesSharedKey, bobEncryptionPublicKey);

// local copy of the AES key that @alice maintains - shared_key.bob@alice
var sharedKeyEncryptedWithAlicePublicKey =
EncryptionUtil.encryptKey(aesSharedKey, aliceEncryptionPublicKey);

var bobPublicKeyCheckSum =
EncryptionUtil.md5CheckSum(bobEncryptionPublicKey);
var location = 'California';

// set atChops for alice
AtChopsKeys atChopsKeys = AtChopsKeys.create(aliceEncryptionKeyPair, null);
var atChopsImpl = AtChopsImpl(atChopsKeys);
when(() => mockAtClient.atChops).thenAnswer((_) => atChopsImpl);
when(() => mockAtClient.getCurrentAtSign()).thenReturn('@alice');
when(() => mockLocalSecondary.getEncryptionPublicKey('@alice'))
.thenAnswer((_) => Future.value(aliceEncryptionPublicKey));
when(() => mockLocalSecondary.executeVerb(any<LLookupVerbBuilder>()))
.thenAnswer((Invocation invocation) {
final builder = invocation.positionalArguments[0] as LLookupVerbBuilder;
final buildKeyValue = builder.buildKey();
if (buildKeyValue == 'shared_key.bob@alice') {
return Future.value('data:$sharedKeyEncryptedWithAlicePublicKey');
} else if (buildKeyValue == 'cached:public:publickey@bob') {
return Future.value('data:$bobEncryptionPublicKey');
} else if (buildKeyValue == '@bob:shared_key@alice') {
return Future.value('data:$sharedKeyEncryptedWithBobPublicKey');
} else {
return Future.value('data:null');
}
});
var sharedKey = AtKey()
..sharedBy = '@alice'
..sharedWith = '@bob'
..key = 'location';
// random IV string
var ivBase64String = 'YmFzZTY0IGVuY29kaW5n';
sharedKey.metadata = Metadata()
..pubKeyCS = bobPublicKeyCheckSum
..ivNonce = ivBase64String;
var encryptionResult =
await sharedKeyEncryption.encrypt(sharedKey, location);
expect(encryptionResult != location, true);
var decryptionResult =
await sharedKeyDecryption.decrypt(sharedKey, encryptionResult);
expect(decryptionResult, location);
});
test(
'test to check shared key encryption throws exception when passed value is not string type',
() async {
var sharedKeyEncryption = SharedKeyEncryption(mockAtClient);
var selfKey = AtKey()
..sharedBy = '@alice'
..sharedWith = '@bob'
..key = 'location';
var locations = ['new jersey', 'new york'];
expect(
() async => await sharedKeyEncryption.encrypt(selfKey, locations),
throwsA(predicate((dynamic e) =>
e is AtEncryptionException &&
e.message ==
'Invalid value type found: List<String>. Valid value type is String')));
});
}
Loading

0 comments on commit 03e9ab0

Please sign in to comment.