• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vaariance / web3-signers / #10

15 Jan 2026 03:08PM UTC coverage: 94.705% (-0.01%) from 94.715%
#10

push

code-z2
feat: Rework ABI encoding and parsing, remove EIP-7702 dependency, and update the Signer interface with sync and async methods.

194 of 205 new or added lines in 4 files covered. (94.63%)

5 existing lines in 3 files now uncovered.

948 of 1001 relevant lines covered (94.71%)

2.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.3
/lib/src/core/core.dart
1
part of '../../web3_signers.dart';
2

3
/// Generates a new random secp256k1 private key.
4
///
5
/// Uses `PointyCastle`'s `ECKeyGenerator` seeded with a cryptographically secure
6
/// random number generator ([Random.secure]).
7
///
8
/// Returns a 32-byte [Bytes] list representing the private key.
9
Bytes generatePrivateKey() {
1✔
10
  final generator = ECKeyGenerator();
1✔
11
  generator.init(
1✔
12
    ParametersWithRandom(
1✔
13
      ECKeyGeneratorParameters(ECCurve_secp256k1()),
2✔
14
      RandomBridge(Random.secure()),
2✔
15
    ),
16
  );
17
  final keyPair = generator.generateKeyPair();
1✔
18
  return unsignedIntToBytes(keyPair.privateKey.d!);
3✔
19
}
20

21
/// Generates a new key pair using the platform's secure hardware authenticator.
22
///
23
/// This function coordinates with the [PlatformAuthenticator] to create a persistent
24
/// key pair identifying the user or device.
25
///
26
/// - [config]: Configuration parameters including the key tag and platform-specific options.
27
/// - [checkExisting]: If `true`, attempts to retrieve an existing public key for the tag before creating a new one. Defaults to `false`.
28
/// - [auth]: Optional instance of [PlatformAuthenticator]. Defaults to a new instance.
29
///
30
/// Returns a [PlatformPublicKey] containing the purely public components (X and Y coordinates).
31
///
32
/// Throws [FormatException] if the returned public key is invalid.
33
///
34
/// Example:
35
/// ```dart
36
/// final config = PlatformConfig(
37
///   keyTag: 'com.example.app.signing_key',
38
///   androidOptions: AndroidPlatformOptions(useStrongBoxKeyMint: true),
39
/// );
40
/// final publicKey = await generatePlatformKey(config: config);
41
/// ```
42
Future<PlatformPublicKey> generatePlatformKey({
1✔
43
  required PlatformConfig config,
44
  bool checkExisting = false,
45
  PlatformAuthenticator? auth,
46
}) async {
47
  auth ??= PlatformAuthenticator();
×
48

49
  Bytes? pubKeyBytes;
50

51
  if (checkExisting) {
52
    pubKeyBytes = await auth.getPublicKey(config.keyTag);
2✔
53
  }
54

55
  pubKeyBytes ??= await auth.createKey(config.keyTag, (
2✔
56
    android: config.androidOptions ?? AndroidPlatformOptions(),
2✔
57
    darwin: config.darwinOptions ?? DarwinPlatformOptions(),
2✔
58
    windows: config.windowsOptions ?? WindowsPlatformOptions(),
2✔
59
  ));
60
  if (pubKeyBytes.length != 65 || pubKeyBytes[0] != 0x04) {
4✔
61
    throw FormatException("Invalid public key format from platform");
1✔
62
  }
63
  final x = Uint256.fromBytes(pubKeyBytes.sublist(1, 33));
2✔
64
  final y = Uint256.fromBytes(pubKeyBytes.sublist(33, 65));
2✔
65

66
  return PlatformPublicKey(x: x, y: y);
1✔
67
}
68

69
/// Registers a new WebAuthn/Passkey credential with a relying party.
70
///
71
/// This function handles the creation of a new passkey credential, including
72
/// setting up the user entity, selection criteria, and parsing the attestation response.
73
///
74
/// - [config]: Configuration for the passkey registration (RP ID, timeout, etc.).
75
/// - [username]: The human-readable name of the user (e.g., email address).
76
/// - [displayname]: The display name of the user.
77
/// - [userIdBase64]: Optional Base64 encoded user ID. If null, a random UUIDv4 is generated.
78
/// - [challenge]: Optional Base64 encoded challenge. If null, a random challenge is generated.
79
/// - [attestationLevel]: The desired attestation level. Defaults to [PasskeyAttestationLevel.none].
80
/// - [excludedCredentials]: A list of credential IDs to exclude (to prevent re-registration).
81
/// - [auth]: Optional instance of [PasskeyAuthenticator]. Defaults to a new instance.
82
///
83
/// Returns a [PassKeyPublicKey] containing the public key coordinates and credential metadata.
84
///
85
/// Example:
86
/// ```dart
87
/// final config = PassKeyConfig(rpId: 'example.com', rpName: 'Example App');
88
/// final credential = await generatePassKey(
89
///   config: config,
90
///   username: 'user@example.com',
91
///   displayname: 'User Name',
92
/// );
93
/// ```
94
Future<PassKeyPublicKey> generatePassKey({
1✔
95
  required PassKeyConfig config,
96
  required String username,
97
  required String displayname,
98
  String? userIdBase64,
99
  String? challenge,
100
  PasskeyAttestationLevel attestationLevel = PasskeyAttestationLevel.none,
101
  List<Bytes> excludedCredentials = const [],
102
  PasskeyAuthenticator? auth,
103
}) async {
UNCOV
104
  auth ??= PasskeyAuthenticator();
×
105

106
  final entity = RegisterRequestType(
1✔
107
    challenge: challenge ?? b64e(getRandomValues()),
2✔
108
    relyingParty: RelyingPartyType(id: config.rpId, name: config.rpName),
3✔
109
    user: UserType(
1✔
110
      id: userIdBase64 ?? b64e(generateUuidV4()),
2✔
111
      displayName: displayname,
112
      name: username,
113
    ),
114
    authSelectionType: AuthenticatorSelectionType(
1✔
115
      requireResidentKey: config.requireResidentKey,
1✔
116
      residentKey: config.residentKey,
1✔
117
      authenticatorAttachment: config.authenticatorAttachment,
1✔
118
      userVerification: config.userVerification,
1✔
119
    ),
120
    pubKeyCredParams: [PubKeyCredParamType(type: 'public-key', alg: -7)],
3✔
121
    timeout: config.timeout,
1✔
122
    attestation: attestationLevel.name,
1✔
123
    excludeCredentials: _parseExcludedCredentials(excludedCredentials, config),
1✔
124
  );
125

126
  final attestation = await auth.register(entity);
1✔
127
  final (pubKey, credentialId, aaGuid) = _parsePassKeyResponse(attestation);
1✔
128

129
  return PassKeyPublicKey(
1✔
130
    x: pubKey!.$1,
131
    y: pubKey.$2,
132
    credentialId: credentialId,
133
    aaGuid: aaGuid,
134
    userName: username,
135
  );
136
}
137

138
List<CredentialType> _parseExcludedCredentials(
1✔
139
  List<Bytes> list,
140
  PassKeyConfig config,
141
) {
142
  return list
143
      .map(
1✔
144
        (e) => CredentialType(
2✔
145
          type: 'public-key',
146
          id: b64e(e),
1✔
147
          transports: config.transports.map((t) => t.transport).toList(),
5✔
148
        ),
149
      )
150
      .toList();
1✔
151
}
152

153
((Uint256, Uint256)?, Bytes, String) _parsePassKeyResponse(
1✔
154
  RegisterResponseType attestation,
155
) {
156
  final attestationAsCbor = b64d(attestation.attestationObject);
2✔
157
  final authdata = extractCBORPattern(attestationAsCbor);
1✔
158
  // Extract the length of the public key from the authentication data.
159
  final l = (authdata![53] << 8) + authdata[54];
4✔
160
  // Calculate the offset for the start of the public key data.
161
  final publicKeyOffset = 55 + l;
1✔
162
  // Extract the public key data from the authentication data.
163
  final pKey = authdata.sublist(publicKeyOffset);
1✔
164
  // Extract the credential ID from the authentication data.
165
  final Bytes credentialId = authdata.sublist(55, publicKeyOffset);
1✔
166
  // Extract and encode the aaGUID from the authentication data.
167
  final aaGuid = base64Url.encode(authdata.sublist(37, 53));
2✔
168
  // Decode the CBOR-encoded public key and convert it to a map.
169
  final decodedPubKey = extractXYFromCoseKey(pKey);
1✔
170
  return (decodedPubKey, credentialId, aaGuid);
171
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc