diff --git a/CHANGELOG.md b/CHANGELOG.md index bb982cc..181dcb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.0.13 + +- returned raw credential from Passkey Signature +- made random challenge generator public + ## 0.0.12 - register function requires display name diff --git a/lib/src/interfaces/interfaces.dart b/lib/src/interfaces/interfaces.dart index da2cae8..4c8ba05 100644 --- a/lib/src/interfaces/interfaces.dart +++ b/lib/src/interfaces/interfaces.dart @@ -2,7 +2,8 @@ library interfaces; import 'dart:typed_data'; -import 'package:blockchain_utils/tuple/tuple.dart'; +import 'package:blockchain_utils/utils/utils.dart'; +import 'package:passkeys/types.dart'; import 'package:web3dart/crypto.dart'; import 'package:web3dart/web3dart.dart'; diff --git a/lib/src/interfaces/passkey_signer_interface.dart b/lib/src/interfaces/passkey_signer_interface.dart index 07f68d3..a4f1c07 100644 --- a/lib/src/interfaces/passkey_signer_interface.dart +++ b/lib/src/interfaces/passkey_signer_interface.dart @@ -7,7 +7,7 @@ abstract class PasskeySignerInterface extends MultiSignerInterface { PassKeysOptions get opts; /// Gets the credential IDs used by the passkey signer. - Set get credentialIds; + Set get credentialIds; /// Generates the 32-byte client data hash for the given [PassKeysOptions] and optional challenge. /// @@ -77,7 +77,7 @@ abstract class PasskeySignerInterface extends MultiSignerInterface { /// /// Parameters: /// - [hash]: The hash to be signed. - /// - [index]: Optional index of the credentialId associated with the PassKeyPair. + /// - [knownCredentials]: Optional credentials to be used for signing. /// /// Returns a Future representing the PassKeySignature of the signed hash. /// @@ -88,5 +88,9 @@ abstract class PasskeySignerInterface extends MultiSignerInterface { /// final pkps = PassKeySigner("example", "example.com", "https://example.com"); /// final passKeySignature = await pkps.signToPasskeySignature(hash); /// ``` - Future signToPasskeySignature(Uint8List hash, {int? index}); + Future signToPasskeySignature(Uint8List hash, + {List? knownCredentials}); + + /// Generates a random base64 string. + String randomBase64String(); } diff --git a/lib/src/signers/passkey_signer.dart b/lib/src/signers/passkey_signer.dart index 4c1a6b9..75fadae 100644 --- a/lib/src/signers/passkey_signer.dart +++ b/lib/src/signers/passkey_signer.dart @@ -18,7 +18,7 @@ class PassKeyPair { final String username; final String? displayname; - final DateTime registrationTime; + final DateTime? registrationTime; PassKeyPair( this.authData, this.username, this.displayname, this.registrationTime); @@ -38,7 +38,9 @@ class PassKeyPair { ), map['username'], map['displayname'], - DateTime.fromMillisecondsSinceEpoch(map['registrationTime']), + map['registrationTime'] != null + ? DateTime.fromMillisecondsSinceEpoch(map['registrationTime']) + : null, ); } @@ -53,13 +55,14 @@ class PassKeyPair { 'username': username, 'displayname': displayname, 'aaGUID': authData.aaGUID, - 'registrationTime': registrationTime.millisecondsSinceEpoch, + 'registrationTime': registrationTime?.millisecondsSinceEpoch, }; } } class PassKeySignature { - final Hex credentialHex; + final Hex hexCredential; + final Bytes rawCredential; /// r and s values of the signature. final Tuple signature; @@ -70,8 +73,8 @@ class PassKeySignature { /// not decodable. final String userId; - PassKeySignature(this.credentialHex, this.signature, this.authData, - this.clientDataPrefix, this.clientDataSuffix, this.userId); + PassKeySignature(this.hexCredential, this.rawCredential, this.signature, + this.authData, this.clientDataPrefix, this.clientDataSuffix, this.userId); /// Converts the `PassKeySignature` to a `Uint8List` using the specified ABI encoding. /// @@ -103,7 +106,7 @@ class PassKeySigner implements PasskeySignerInterface { final PasskeyAuthenticator _auth; - final Set _knownCredentials; + final Set _knownCredentials; @override String dummySignature = @@ -114,7 +117,7 @@ class PassKeySigner implements PasskeySignerInterface { /// - [origin] : the relying party entity origin. e.g "https://variance.space" /// - [knownCredentials] : a set of known credentials. Defaults to an empty set. PassKeySigner(String namespace, String name, String origin, - {Set knownCredentials = const {}}) + {Set knownCredentials = const {}}) : _opts = PassKeysOptions( namespace: namespace, name: name, @@ -124,14 +127,14 @@ class PassKeySigner implements PasskeySignerInterface { _knownCredentials = knownCredentials; @override - Set get credentialIds => _knownCredentials; + Set get credentialIds => _knownCredentials; @override PassKeysOptions get opts => _opts; @override Uint8List clientDataHash(PassKeysOptions options, [String? challenge]) { - options.challenge = challenge ?? _randomBase64String(); + options.challenge = challenge ?? randomBase64String(); final clientDataJson = jsonEncode({ "type": options.type, "challenge": options.challenge, @@ -157,8 +160,7 @@ class PassKeySigner implements PasskeySignerInterface { @override String getAddress({int? index}) { - return base64Url - .encode(hexToCredentialId(_knownCredentials.elementAt(index ?? 0))); + return base64Url.encode(_knownCredentials.elementAt(index ?? 0)); } @override @@ -177,10 +179,32 @@ class PassKeySigner implements PasskeySignerInterface { @override Future personalSign(Uint8List hash, {int? index}) async { - final signature = await signToPasskeySignature(hash, index: index); + final knownCredentials = _getKnownCredentials(index); + final signature = + await signToPasskeySignature(hash, knownCredentials: knownCredentials); return signature.toUint8List(); } + List _getKnownCredentials([int? index]) { + // Retrive known credentials if any + final List credentialIds; + if (index != null) { + credentialIds = _knownCredentials.elementAtOrNull(index) != null + ? [_knownCredentials.elementAt(index)] + : _knownCredentials.toList(); + } else { + credentialIds = _knownCredentials.toList(); + } + + // convert credentialIds to CredentialType + final List credentials = credentialIds + .map((e) => + CredentialType(type: "public-key", id: b64e(e), transports: [])) + .toList(); + + return credentials; + } + @override Future register(String username, String displayname, {String? challenge, @@ -205,35 +229,21 @@ class PassKeySigner implements PasskeySignerInterface { @override Future signToEc(Uint8List hash, {int? index}) async { - final signature = await signToPasskeySignature(hash, index: index); + final knownCredentials = _getKnownCredentials(index); + final signature = + await signToPasskeySignature(hash, knownCredentials: knownCredentials); return MsgSignature( signature.signature.item1.value, signature.signature.item2.value, 0); } @override Future signToPasskeySignature(Uint8List hash, - {int? index}) async { + {List? knownCredentials}) async { // Prepare hash final hashBase64 = b64e(hash); - // Retrive known credentials if any - final List credentialIds; - if (index != null) { - credentialIds = _knownCredentials.elementAtOrNull(index) != null - ? [_knownCredentials.elementAt(index)] - : _knownCredentials.toList(); - } else { - credentialIds = _knownCredentials.toList(); - } - - // convert credentialIds to CredentialType - final List credentials = credentialIds - .map((e) => CredentialType( - type: "public-key", id: b64e(hexToCredentialId(e)), transports: [])) - .toList(); - // Authenticate with passkey - final assertion = await _authenticate(hashBase64, credentials, true); + final assertion = await _authenticate(hashBase64, knownCredentials, true); // Extract signature from response final sig = getMessagingSignature(b64d(assertion.signature)); @@ -247,6 +257,7 @@ class PassKeySigner implements PasskeySignerInterface { return PassKeySignature( credentialIdToHex(b64d(assertion.id).toList()), + b64d(assertion.rawId), sig, b64d(assertion.authenticatorData), challengePrefix, @@ -316,7 +327,8 @@ class PassKeySigner implements PasskeySignerInterface { return _decode(authData); } - String _randomBase64String() { + @override + String randomBase64String() { final uuid = UUID.generateUUIDv4(); return b64e(UUID.toBuffer(uuid)); } @@ -334,7 +346,7 @@ class PassKeySigner implements PasskeySignerInterface { name: options.name, ), user: UserType( - id: _randomBase64String(), + id: randomBase64String(), displayName: displayname, name: username, ), diff --git a/lib/src/vendor/vendor.dart b/lib/src/vendor/vendor.dart index b7f9655..6b3d229 100644 --- a/lib/src/vendor/vendor.dart +++ b/lib/src/vendor/vendor.dart @@ -1,7 +1,7 @@ import 'dart:math'; import 'dart:typed_data'; -import 'package:blockchain_utils/tuple/tuple.dart'; +import 'package:blockchain_utils/utils/utils.dart'; import 'package:web3dart/crypto.dart'; import '../utils/utils.dart' show hexToU8a; diff --git a/lib/src/web3_signers_base.dart b/lib/src/web3_signers_base.dart index 1296fdf..a41ab4e 100644 --- a/lib/src/web3_signers_base.dart +++ b/lib/src/web3_signers_base.dart @@ -5,7 +5,6 @@ import 'dart:convert'; import 'dart:math'; import 'dart:typed_data'; -import 'package:blockchain_utils/bip/mnemonic/mnemonic.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:passkeys/authenticator.dart'; import 'package:passkeys/types.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 218f9c1..bdd93ef 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: web3_signers description: Web3 signers provides a uniform interface for signing EIP-1271 messages with different EC algorithms. -version: 0.0.12 +version: 0.0.13 homepage: https://variance.space repository: https://github.com/vaariance/web3-signers issue_tracker: https://github.com/vaariance/web3-signers/issues