Skip to content

Commit

Permalink
feat: Added did:jwk p256 and code optimisation #2034
Browse files Browse the repository at this point in the history
  • Loading branch information
bibash28 committed Oct 31, 2023
1 parent cd3d9fe commit d5add94
Show file tree
Hide file tree
Showing 22 changed files with 376 additions and 728 deletions.
1 change: 1 addition & 0 deletions lib/app/shared/constants/secure_storage_keys.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class SecureStorageKeys {

static const String p256PrivateKey = 'p256PrivateKey';
static const String p256PrivateKey2 = 'p256PrivateKey2';
static const String p256PrivateKey3 = 'p256PrivateKey3';

static const String cryptoAccount = 'cryptoAccount';
static const String cryptoAccounTrackingIndex = 'cryptoAccounTrackingIndex';
Expand Down
32 changes: 31 additions & 1 deletion lib/app/shared/enum/type/did_key_type.dart
Original file line number Diff line number Diff line change
@@ -1 +1,31 @@
enum DidKeyType { secp256k1, p256, ebsiv3 }
import 'package:altme/l10n/l10n.dart';

enum DidKeyType { secp256k1, p256, ebsiv3, jwkP256 }

extension DidKeyTypeX on DidKeyType {
String get formattedString {
switch (this) {
case DidKeyType.secp256k1:
return 'did:key secp256k1';
case DidKeyType.p256:
return 'did:key P-256';
case DidKeyType.ebsiv3:
return 'did:key EBSI-V3';
case DidKeyType.jwkP256:
return 'did:jwk P-256';
}
}

String getTitle(AppLocalizations l10n) {
switch (this) {
case DidKeyType.secp256k1:
return l10n.manageKeyDecentralizedIDSecp256k1;
case DidKeyType.p256:
return l10n.keyDecentralizedIDP256;
case DidKeyType.ebsiv3:
return l10n.manageEbsiV3DecentralizedId;
case DidKeyType.jwkP256:
return l10n.jwkDecentralizedIDP256;
}
}
}
205 changes: 127 additions & 78 deletions lib/app/shared/helper_functions/helper_functions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -245,85 +245,94 @@ Future<String> web3RpcMainnetInfuraURL() async {
return '$prefixUrl$infuraApiKey';
}

Future<String> getEBSIV3P256PrivateKey(
SecureStorageProvider secureStorage,
) async {
final String? p256PrivateKey = await secureStorage.get(
SecureStorageKeys.p256PrivateKey,
);
Future<String> getPrivateKey({
required SecureStorageProvider secureStorage,
required DidKeyType didKeyType,
OIDC4VC? oidc4vc,
}) async {
late String storageKey;

if (didKeyType == DidKeyType.secp256k1) {
if (oidc4vc == null) throw Exception();
final mnemonic = await secureStorage.get(SecureStorageKeys.ssiMnemonic);
final index = getIndexValue(isEBSIV3: true);
final key = await oidc4vc.privateKeyFromMnemonic(
mnemonic: mnemonic!,
indexValue: index,
);
return key;
}

if (p256PrivateKey == null) {
final jwk = JsonWebKey.generate('ES256');
/// for other than DidKeyType.secp256k1
final json = jwk.toJson();
switch (didKeyType) {
case DidKeyType.secp256k1:
throw Exception();

// Sort the keys in ascending order and remove alg
final sortedJwk = Map.fromEntries(
json.entries.toList()..sort((e1, e2) => e1.key.compareTo(e2.key)),
)..remove('keyOperations');
case DidKeyType.p256:
storageKey = SecureStorageKeys.p256PrivateKey;
case DidKeyType.ebsiv3:
storageKey = SecureStorageKeys.p256PrivateKey2;
case DidKeyType.jwkP256:
storageKey = SecureStorageKeys.p256PrivateKey3;
}

await secureStorage.set(
SecureStorageKeys.p256PrivateKey,
jsonEncode(sortedJwk),
);
final String? p256PrivateKey = await secureStorage.get(storageKey);

return jsonEncode(sortedJwk);
} else {
return p256PrivateKey;
}
}
if (p256PrivateKey != null) return p256PrivateKey;

Future<String> getP256PrivateKey(SecureStorageProvider secureStorage) async {
final String? p256PrivateKey = await secureStorage.get(
SecureStorageKeys.p256PrivateKey2,
);
final jwk = JsonWebKey.generate('ES256');

if (p256PrivateKey == null) {
final jwk = JsonWebKey.generate('ES256');
final json = jwk.toJson();

final json = jwk.toJson();
// Sort the keys in ascending order and remove alg
final sortedJwk = Map.fromEntries(
json.entries.toList()..sort((e1, e2) => e1.key.compareTo(e2.key)),
)..remove('keyOperations');

// Sort the keys in ascending order and remove alg
final sortedJwk = Map.fromEntries(
json.entries.toList()..sort((e1, e2) => e1.key.compareTo(e2.key)),
)..remove('keyOperations');
await secureStorage.set(storageKey, jsonEncode(sortedJwk));

await secureStorage.set(
SecureStorageKeys.p256PrivateKey2,
jsonEncode(sortedJwk),
);
return jsonEncode(sortedJwk);
}

return jsonEncode(sortedJwk);
} else {
return p256PrivateKey;
DidKeyType? getDidKeyFromString(String? didKeyTypeString) {
if (didKeyTypeString == null) return null;
for (final name in DidKeyType.values) {
if (name.toString() == didKeyTypeString) {
return name;
}
}
return null;
}

Future<String> fetchPrivateKey({
required SecureStorageProvider secureStorage,
required bool? isEBSIV3,
bool? isEBSIV3,
OIDC4VC? oidc4vc,
}) async {
late String privateKey;

final didKeyType = await secureStorage.get(SecureStorageKeys.didKeyType);
if (isEBSIV3 != null && isEBSIV3) {
final privateKey = await getPrivateKey(
secureStorage: secureStorage,
didKeyType: DidKeyType.ebsiv3,
);

if ((isEBSIV3 != null && isEBSIV3) ||
didKeyType == DidKeyType.ebsiv3.toString()) {
privateKey = await getEBSIV3P256PrivateKey(secureStorage);
} else {
if (didKeyType == DidKeyType.secp256k1.toString()) {
if (oidc4vc == null) throw Exception();
final mnemonic = await secureStorage.get(SecureStorageKeys.ssiMnemonic);
final index = getIndexValue(isEBSIV3: true);
privateKey = await oidc4vc.privateKeyFromMnemonic(
mnemonic: mnemonic!,
indexValue: index,
);
} else {
privateKey = await getP256PrivateKey(secureStorage);
}
return privateKey;
}

/// other cases
final didKeyTypeString =
await secureStorage.get(SecureStorageKeys.didKeyType);

final didKeyType = getDidKeyFromString(didKeyTypeString);

if (didKeyType == null) throw Exception();

final privateKey = await getPrivateKey(
secureStorage: secureStorage,
didKeyType: didKeyType,
oidc4vc: oidc4vc,
);

return privateKey;
}

Expand Down Expand Up @@ -421,35 +430,75 @@ String getUtf8Message(String maybeHex) {
Future<(String, String)> getDidAndKid({
required String privateKey,
required SecureStorageProvider secureStorage,
required bool? isEBSIV3,
required DidKeyType didKeyType,
DIDKitProvider? didKitProvider,
}) async {
late String did;
late String kid;

final didKeyType = await secureStorage.get(SecureStorageKeys.didKeyType);

if ((isEBSIV3 != null && isEBSIV3) ||
didKeyType == DidKeyType.ebsiv3.toString()) {
final private = jsonDecode(privateKey) as Map<String, dynamic>;
switch (didKeyType) {
case DidKeyType.ebsiv3:
final private = jsonDecode(privateKey) as Map<String, dynamic>;

//b'\xd1\xd6\x03' in python
final List<int> prefixByteList = [0xd1, 0xd6, 0x03];
final List<int> prefix = prefixByteList.map((byte) => byte).toList();

final encodedData = sortedPublcJwk(private);
final encodedAddress = Base58Encode([...prefix, ...encodedData]);

did = 'did:key:z$encodedAddress';
final String lastPart = did.split(':')[2];
kid = '$did#$lastPart';
case DidKeyType.jwkP256:
final private = jsonDecode(privateKey) as Map<String, dynamic>;
final base64EncodedJWK = base64UrlEncode(utf8.encode(private.toString()));
did = 'did:jwk:$base64EncodedJWK';

kid = '$did#0';
case DidKeyType.p256:
case DidKeyType.secp256k1:
if (didKitProvider == null) throw Exception();
const didMethod = AltMeStrings.defaultDIDMethod;
did = didKitProvider.keyToDID(didMethod, privateKey);
kid = await didKitProvider.keyToVerificationMethod(didMethod, privateKey);
}

//b'\xd1\xd6\x03' in python
final List<int> prefixByteList = [0xd1, 0xd6, 0x03];
final List<int> prefix = prefixByteList.map((byte) => byte).toList();
return (did, kid);
}

final encodedData = sortedPublcJwk(private);
final encodedAddress = Base58Encode([...prefix, ...encodedData]);
Future<(String, String)> fetchDidAndKid({
required String privateKey,
bool? isEBSIV3,
required SecureStorageProvider secureStorage,
DIDKitProvider? didKitProvider,
}) async {
if (isEBSIV3 != null && isEBSIV3) {
final (did, kid) = await getDidAndKid(
didKeyType: DidKeyType.ebsiv3,
privateKey: privateKey,
didKitProvider: DIDKitProvider(),
secureStorage: getSecureStorage,
);

did = 'did:key:z$encodedAddress';
final String lastPart = did.split(':')[2];
kid = '$did#$lastPart';
} else {
if (didKitProvider == null) throw Exception();
const didMethod = AltMeStrings.defaultDIDMethod;
did = didKitProvider.keyToDID(didMethod, privateKey);
kid = await didKitProvider.keyToVerificationMethod(didMethod, privateKey);
return (did, kid);
}

/// other cases
final didKeyTypeString =
await secureStorage.get(SecureStorageKeys.didKeyType);

final didKeyType = getDidKeyFromString(didKeyTypeString);

if (didKeyType == null) throw Exception();

final (did, kid) = await getDidAndKid(
didKeyType: didKeyType,
privateKey: privateKey,
didKitProvider: DIDKitProvider(),
secureStorage: getSecureStorage,
);

return (did, kid);
}

Expand Down
Loading

0 comments on commit d5add94

Please sign in to comment.