@reegaviljoen/eldlock 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/README.md +285 -0
  2. package/bin/eldlock +11 -0
  3. package/docs/architecture.md +164 -0
  4. package/docs/threat-model.md +47 -0
  5. package/eldlock-cli/README.md +56 -0
  6. package/eldlock-cli/bin/eldlock +3 -0
  7. package/eldlock-cli/package-lock.json +805 -0
  8. package/eldlock-cli/package.json +71 -0
  9. package/eldlock-cli/src/api.ts +250 -0
  10. package/eldlock-cli/src/cli.ts +490 -0
  11. package/eldlock-cli/src/main.ts +10 -0
  12. package/eldlock-cli/src/tui.ts +676 -0
  13. package/eldlock-cli/tsconfig.json +13 -0
  14. package/eldlock-cli/vendor/npm/ansi-regex-6.2.2.tgz +0 -0
  15. package/eldlock-cli/vendor/npm/bun-ffi-structs-0.2.2.tgz +0 -0
  16. package/eldlock-cli/vendor/npm/diff-9.0.0.tgz +0 -0
  17. package/eldlock-cli/vendor/npm/emoji-regex-10.6.0.tgz +0 -0
  18. package/eldlock-cli/vendor/npm/esbuild-0.28.0.tgz +0 -0
  19. package/eldlock-cli/vendor/npm/esbuild-darwin-arm64-0.28.0.tgz +0 -0
  20. package/eldlock-cli/vendor/npm/esbuild-darwin-x64-0.28.0.tgz +0 -0
  21. package/eldlock-cli/vendor/npm/esbuild-linux-arm64-0.28.0.tgz +0 -0
  22. package/eldlock-cli/vendor/npm/esbuild-linux-x64-0.28.0.tgz +0 -0
  23. package/eldlock-cli/vendor/npm/fsevents-2.3.3.tgz +0 -0
  24. package/eldlock-cli/vendor/npm/get-east-asian-width-1.6.0.tgz +0 -0
  25. package/eldlock-cli/vendor/npm/marked-17.0.1.tgz +0 -0
  26. package/eldlock-cli/vendor/npm/opentui-core-0.3.1.tgz +0 -0
  27. package/eldlock-cli/vendor/npm/opentui-core-darwin-arm64-0.3.1.tgz +0 -0
  28. package/eldlock-cli/vendor/npm/opentui-core-darwin-x64-0.3.1.tgz +0 -0
  29. package/eldlock-cli/vendor/npm/opentui-core-linux-arm64-0.3.1.tgz +0 -0
  30. package/eldlock-cli/vendor/npm/opentui-core-linux-x64-0.3.1.tgz +0 -0
  31. package/eldlock-cli/vendor/npm/string-width-7.2.0.tgz +0 -0
  32. package/eldlock-cli/vendor/npm/strip-ansi-7.1.2.tgz +0 -0
  33. package/eldlock-cli/vendor/npm/tsx-4.22.4.tgz +0 -0
  34. package/eldlock-cli/vendor/npm/types-node-22.19.19.tgz +0 -0
  35. package/eldlock-cli/vendor/npm/typescript-5.9.3.tgz +0 -0
  36. package/eldlock-cli/vendor/npm/undici-types-6.21.0.tgz +0 -0
  37. package/eldlock-cli/vendor/npm/web-tree-sitter-0.25.10.tgz +0 -0
  38. package/eldlock-cli/vendor/npm/yoga-layout-3.2.1.tgz +0 -0
  39. package/eldlock-server/cmd/eldlock-server/main.go +132 -0
  40. package/eldlock-server/go.mod +10 -0
  41. package/eldlock-server/go.sum +11 -0
  42. package/eldlock-server/internal/api/README.md +14 -0
  43. package/eldlock-server/internal/api/core.go +126 -0
  44. package/eldlock-server/internal/api/exec.go +97 -0
  45. package/eldlock-server/internal/api/secrets.go +358 -0
  46. package/eldlock-server/internal/api/server.go +72 -0
  47. package/eldlock-server/internal/api/service_test.go +416 -0
  48. package/eldlock-server/internal/api/types.go +48 -0
  49. package/eldlock-server/internal/api/vault.go +69 -0
  50. package/eldlock-server/internal/api/vendor.go +44 -0
  51. package/eldlock-server/internal/libfido2/LICENSE +21 -0
  52. package/eldlock-server/internal/libfido2/README.md +127 -0
  53. package/eldlock-server/internal/libfido2/examples_test.go +614 -0
  54. package/eldlock-server/internal/libfido2/fido2.go +1234 -0
  55. package/eldlock-server/internal/libfido2/fido2_darwin.go +7 -0
  56. package/eldlock-server/internal/libfido2/fido2_other.go +9 -0
  57. package/eldlock-server/internal/libfido2/fido2_test.go +101 -0
  58. package/eldlock-server/internal/libfido2/go.mod +10 -0
  59. package/eldlock-server/internal/libfido2/go.sum +16 -0
  60. package/eldlock-server/internal/libfido2/log.go +87 -0
  61. package/eldlock-server/internal/store/README.md +7 -0
  62. package/eldlock-server/internal/store/store.go +434 -0
  63. package/eldlock-server/internal/store/store_test.go +125 -0
  64. package/eldlock-server/internal/yubikey/README.md +25 -0
  65. package/eldlock-server/internal/yubikey/default_fido2.go +7 -0
  66. package/eldlock-server/internal/yubikey/default_stub.go +7 -0
  67. package/eldlock-server/internal/yubikey/fido2_disabled.go +9 -0
  68. package/eldlock-server/internal/yubikey/fido2_libfido2.go +225 -0
  69. package/eldlock-server/internal/yubikey/fido2_libfido2_test.go +66 -0
  70. package/eldlock-server/internal/yubikey/passkey.go +139 -0
  71. package/eldlock-server/internal/yubikey/passkey_test.go +36 -0
  72. package/eldlock-server/vendor/github.com/keys-pub/go-libfido2/LICENSE +21 -0
  73. package/eldlock-server/vendor/github.com/keys-pub/go-libfido2/README.md +127 -0
  74. package/eldlock-server/vendor/github.com/keys-pub/go-libfido2/fido2.go +1234 -0
  75. package/eldlock-server/vendor/github.com/keys-pub/go-libfido2/fido2_darwin.go +7 -0
  76. package/eldlock-server/vendor/github.com/keys-pub/go-libfido2/fido2_other.go +9 -0
  77. package/eldlock-server/vendor/github.com/keys-pub/go-libfido2/log.go +87 -0
  78. package/eldlock-server/vendor/github.com/pkg/errors/.travis.yml +10 -0
  79. package/eldlock-server/vendor/github.com/pkg/errors/LICENSE +23 -0
  80. package/eldlock-server/vendor/github.com/pkg/errors/Makefile +44 -0
  81. package/eldlock-server/vendor/github.com/pkg/errors/README.md +59 -0
  82. package/eldlock-server/vendor/github.com/pkg/errors/appveyor.yml +32 -0
  83. package/eldlock-server/vendor/github.com/pkg/errors/errors.go +288 -0
  84. package/eldlock-server/vendor/github.com/pkg/errors/go113.go +38 -0
  85. package/eldlock-server/vendor/github.com/pkg/errors/stack.go +177 -0
  86. package/eldlock-server/vendor/modules.txt +7 -0
  87. package/examples/eldlock.toml +17 -0
  88. package/install.sh +66 -0
  89. package/package.json +66 -0
  90. package/scripts/build-production.mjs +177 -0
  91. package/scripts/postinstall-production.mjs +23 -0
@@ -0,0 +1,127 @@
1
+ # go-libfido2
2
+
3
+ Go wrapper for libfido2.
4
+
5
+ ```go
6
+ import (
7
+ "github.com/keys-pub/go-libfido2"
8
+ )
9
+
10
+ func ExampleDevice_Assertion() {
11
+ locs, err := libfido2.DeviceLocations()
12
+ if err != nil {
13
+ log.Fatal(err)
14
+ }
15
+ if len(locs) == 0 {
16
+ log.Println("No devices")
17
+ return
18
+ }
19
+
20
+ log.Printf("Using device: %+v\n", locs[0])
21
+ path := locs[0].Path
22
+ device, err := libfido2.NewDevice(path)
23
+ if err != nil {
24
+ log.Fatal(err)
25
+ }
26
+
27
+ cdh := libfido2.RandBytes(32)
28
+ userID := libfido2.RandBytes(32)
29
+ salt := libfido2.RandBytes(32)
30
+ pin := "12345"
31
+
32
+ attest, err := device.MakeCredential(
33
+ cdh,
34
+ libfido2.RelyingParty{
35
+ ID: "keys.pub",
36
+ },
37
+ libfido2.User{
38
+ ID: userID,
39
+ Name: "gabriel",
40
+ },
41
+ libfido2.ES256, // Algorithm
42
+ pin,
43
+ &libfido2.MakeCredentialOpts{
44
+ Extensions: []libfido2.Extension{libfido2.HMACSecretExtension},
45
+ },
46
+ )
47
+ if err != nil {
48
+ log.Fatal(err)
49
+ }
50
+
51
+ log.Printf("Attestation:\n")
52
+ log.Printf("AuthData: %s\n", hex.EncodeToString(attest.AuthData))
53
+ log.Printf("ClientDataHash: %s\n", hex.EncodeToString(attest.ClientDataHash))
54
+ log.Printf("ID: %s\n", hex.EncodeToString(attest.CredentialID))
55
+ log.Printf("Type: %s\n", attest.CredentialType)
56
+ log.Printf("Sig: %s\n", hex.EncodeToString(attest.Sig))
57
+
58
+ assertion, err := device.Assertion(
59
+ "keys.pub",
60
+ cdh,
61
+ [][]byte{attest.CredentialID},
62
+ pin,
63
+ &libfido2.AssertionOpts{
64
+ Extensions: []libfido2.Extension{libfido2.HMACSecretExtension},
65
+ HMACSalt: salt,
66
+ },
67
+ )
68
+ if err != nil {
69
+ log.Fatal(err)
70
+ }
71
+
72
+ log.Printf("Assertion:\n")
73
+ log.Printf("%s\n", hex.EncodeToString(assertion.AuthData))
74
+ log.Printf("%s\n", hex.EncodeToString(assertion.HMACSecret))
75
+ log.Printf("%s\n", hex.EncodeToString(assertion.Sig))
76
+
77
+ // Output:
78
+ //
79
+ }
80
+ ```
81
+
82
+ ## Examples
83
+
84
+ The examples require a device.
85
+
86
+ To run an example, set FIDO2_EXAMPLES=1.
87
+
88
+ ```shell
89
+ FIDO2_EXAMPLES=1 go test -v -run ExampleDeviceLocations
90
+ FIDO2_EXAMPLES=1 go test -v -run ExampleDevice_Assertion
91
+ FIDO2_EXAMPLES=1 go test -v -run ExampleDevice_Credentials
92
+ ```
93
+
94
+ ## Dependencies
95
+
96
+ ### Linux
97
+
98
+ ```shell
99
+ sudo apt install software-properties-common
100
+ sudo apt-add-repository ppa:yubico/stable
101
+ sudo apt update
102
+ sudo apt install libfido2-dev
103
+ ```
104
+
105
+ ### macOS
106
+
107
+ ```shell
108
+ brew install keys-pub/tap/libfido2
109
+ ```
110
+
111
+ ### Windows
112
+
113
+ ```shell
114
+ scoop bucket add keys.pub https://github.com/keys-pub/scoop-bucket
115
+ scoop install libfido2
116
+ ```
117
+
118
+
119
+ ### Building libfido2
120
+
121
+ #### macOS
122
+
123
+ ```shell
124
+ export CFLAGS="-I/usr/local/include -I/usr/local/opt/openssl@1.1/include"
125
+ export LDFLAGS="-L/usr/local/lib -L/usr/local/opt/openssl@1.1/lib/"
126
+ (rm -rf build && mkdir build && cd build && cmake ..) && make -C build
127
+ ```
@@ -0,0 +1,614 @@
1
+ package libfido2_test
2
+
3
+ import (
4
+ "bytes"
5
+ "encoding/hex"
6
+ "log"
7
+ "os"
8
+
9
+ "github.com/keys-pub/go-libfido2"
10
+ )
11
+
12
+ func ExampleDeviceLocations() {
13
+ if os.Getenv("FIDO2_EXAMPLES") != "1" {
14
+ return
15
+ }
16
+ libfido2.SetLogger(libfido2.NewLogger(libfido2.DebugLevel))
17
+
18
+ locs, err := libfido2.DeviceLocations()
19
+ if err != nil {
20
+ log.Fatal(err)
21
+ }
22
+
23
+ for _, loc := range locs {
24
+ log.Printf("%+v\n", loc)
25
+ device, err := libfido2.NewDevice(loc.Path)
26
+ if err != nil {
27
+ log.Fatal(err)
28
+ }
29
+
30
+ hidInfo, err := device.CTAPHIDInfo()
31
+ if err != nil {
32
+ log.Fatal(err)
33
+ }
34
+ log.Printf("CTAPHIDInfo: %+v\n", hidInfo)
35
+
36
+ info, err := device.Info()
37
+ if err != nil {
38
+ log.Fatal(err)
39
+ }
40
+ log.Printf("Info: %+v\n", info)
41
+ }
42
+
43
+ // Output:
44
+ //
45
+ }
46
+
47
+ func ExampleDevice_MakeCredential() {
48
+ if os.Getenv("FIDO2_EXAMPLES") != "1" {
49
+ return
50
+ }
51
+ libfido2.SetLogger(libfido2.NewLogger(libfido2.DebugLevel))
52
+
53
+ locs, err := libfido2.DeviceLocations()
54
+ if err != nil {
55
+ log.Fatal(err)
56
+ }
57
+ if len(locs) == 0 {
58
+ log.Println("No devices")
59
+ return
60
+ }
61
+
62
+ log.Printf("Using device: %+v\n", locs[0])
63
+ path := locs[0].Path
64
+ device, err := libfido2.NewDevice(path)
65
+ if err != nil {
66
+ log.Fatal(err)
67
+ }
68
+
69
+ cdh := libfido2.RandBytes(32)
70
+ userID := libfido2.RandBytes(32)
71
+ pin := "12345"
72
+
73
+ attest, err := device.MakeCredential(
74
+ cdh,
75
+ libfido2.RelyingParty{
76
+ ID: "keys.pub",
77
+ Name: "keys.pub",
78
+ },
79
+ libfido2.User{
80
+ ID: userID,
81
+ Name: "gabriel",
82
+ DisplayName: "Gabriel",
83
+ },
84
+ libfido2.ES256, // Algorithm
85
+ pin,
86
+ nil,
87
+ )
88
+ if err != nil {
89
+ log.Fatal(err)
90
+ }
91
+
92
+ log.Printf("Attestation:\n")
93
+ log.Printf("AuthData: %s\n", hex.EncodeToString(attest.AuthData))
94
+ log.Printf("ClientDataHash: %s\n", hex.EncodeToString(attest.ClientDataHash))
95
+ log.Printf("ID: %s\n", hex.EncodeToString(attest.CredentialID))
96
+ log.Printf("Type: %d\n", attest.CredentialType)
97
+ log.Printf("Sig: %s\n", hex.EncodeToString(attest.Sig))
98
+
99
+ // Output:
100
+ //
101
+ }
102
+
103
+ func ExampleDevice_Assertion() {
104
+ if os.Getenv("FIDO2_EXAMPLES") != "1" {
105
+ return
106
+ }
107
+ locs, err := libfido2.DeviceLocations()
108
+ if err != nil {
109
+ log.Fatal(err)
110
+ }
111
+ if len(locs) == 0 {
112
+ log.Println("No devices")
113
+ return
114
+ }
115
+
116
+ log.Printf("Using device: %+v\n", locs[0])
117
+ path := locs[0].Path
118
+ device, err := libfido2.NewDevice(path)
119
+ if err != nil {
120
+ log.Fatal(err)
121
+ }
122
+
123
+ cdh := libfido2.RandBytes(32)
124
+ userID := libfido2.RandBytes(32)
125
+ salt := libfido2.RandBytes(32)
126
+ pin := "12345"
127
+
128
+ attest, err := device.MakeCredential(
129
+ cdh,
130
+ libfido2.RelyingParty{
131
+ ID: "keys.pub",
132
+ },
133
+ libfido2.User{
134
+ ID: userID,
135
+ Name: "gabriel",
136
+ },
137
+ libfido2.ES256, // Algorithm
138
+ pin,
139
+ &libfido2.MakeCredentialOpts{
140
+ Extensions: []libfido2.Extension{libfido2.HMACSecretExtension},
141
+ RK: libfido2.True,
142
+ },
143
+ )
144
+ if err != nil {
145
+ log.Fatal(err)
146
+ }
147
+
148
+ log.Printf("Attestation:\n")
149
+ log.Printf("AuthData: %s\n", hex.EncodeToString(attest.AuthData))
150
+ log.Printf("ClientDataHash: %s\n", hex.EncodeToString(attest.ClientDataHash))
151
+ log.Printf("ID: %s\n", hex.EncodeToString(attest.CredentialID))
152
+ log.Printf("Type: %s\n", attest.CredentialType)
153
+ log.Printf("Sig: %s\n", hex.EncodeToString(attest.Sig))
154
+
155
+ assertion, err := device.Assertion(
156
+ "keys.pub",
157
+ cdh,
158
+ [][]byte{attest.CredentialID},
159
+ pin,
160
+ &libfido2.AssertionOpts{
161
+ Extensions: []libfido2.Extension{libfido2.HMACSecretExtension},
162
+ UP: libfido2.True,
163
+ HMACSalt: salt,
164
+ },
165
+ )
166
+ if err != nil {
167
+ log.Fatal(err)
168
+ }
169
+
170
+ log.Printf("Assertion:\n")
171
+ log.Printf("AuthDataCBOR: %s\n", hex.EncodeToString(assertion.AuthDataCBOR))
172
+ log.Printf("HMACSecret: %s\n", hex.EncodeToString(assertion.HMACSecret))
173
+ log.Printf("Sig: %s\n", hex.EncodeToString(assertion.Sig))
174
+ log.Printf("CredentialID: %s\n", hex.EncodeToString(assertion.CredentialID))
175
+ log.Printf("User.ID: %s\n", hex.EncodeToString(assertion.User.ID))
176
+
177
+ // Output:
178
+ //
179
+ }
180
+
181
+ func ExampleDevice_Credentials() {
182
+ if os.Getenv("FIDO2_EXAMPLES") != "1" {
183
+ return
184
+ }
185
+ libfido2.SetLogger(libfido2.NewLogger(libfido2.DebugLevel))
186
+
187
+ locs, err := libfido2.DeviceLocations()
188
+ if err != nil {
189
+ log.Fatal(err)
190
+ }
191
+ if len(locs) == 0 {
192
+ log.Println("No devices")
193
+ return
194
+ }
195
+
196
+ log.Printf("Using device: %+v\n", locs[0])
197
+ path := locs[0].Path
198
+ device, err := libfido2.NewDevice(path)
199
+ if err != nil {
200
+ log.Fatal(err)
201
+ }
202
+
203
+ pin := "12345"
204
+
205
+ info, err := device.CredentialsInfo(pin)
206
+ if err != nil {
207
+ log.Fatal(err)
208
+ }
209
+ log.Printf("Info: %+v\n", info)
210
+
211
+ rps, err := device.RelyingParties(pin)
212
+ if err != nil {
213
+ log.Fatal(err)
214
+ }
215
+ for _, rp := range rps {
216
+ log.Printf("RP{ID: %s, Name: %s}\n", rp.ID, rp.Name)
217
+ creds, err := device.Credentials(rp.ID, pin)
218
+ if err != nil {
219
+ log.Fatal(err)
220
+ }
221
+ for _, cred := range creds {
222
+ log.Printf("User{ID: %s, Name: %s}\n", hex.EncodeToString(cred.User.ID), cred.User.Name)
223
+ log.Printf("ID: %s\n", hex.EncodeToString(cred.ID))
224
+ log.Printf("Type: %s\n", cred.Type)
225
+ log.Printf("\n")
226
+ }
227
+ }
228
+
229
+ // Output:
230
+ //
231
+ }
232
+
233
+ func ExampleDevice_Reset() {
234
+ if os.Getenv("FIDO2_EXAMPLES") != "1" {
235
+ return
236
+ }
237
+ libfido2.SetLogger(libfido2.NewLogger(libfido2.DebugLevel))
238
+
239
+ if os.Getenv("FIDO2_EXAMPLES_RESET") != "1" {
240
+ log.Println("only runs if FIDO2_EXAMPLES_RESET=1")
241
+ return
242
+ }
243
+
244
+ locs, err := libfido2.DeviceLocations()
245
+ if err != nil {
246
+ log.Fatal(err)
247
+ }
248
+ if len(locs) == 0 {
249
+ log.Println("No devices")
250
+ return
251
+ }
252
+
253
+ log.Printf("Using device: %+v\n", locs[0])
254
+ path := locs[0].Path
255
+ device, err := libfido2.NewDevice(path)
256
+ if err != nil {
257
+ log.Fatal(err)
258
+ }
259
+
260
+ log.Printf("Resetting: %+v\n", locs[0])
261
+ if err := device.Reset(); err != nil {
262
+ log.Fatal(err)
263
+ }
264
+
265
+ // Output:
266
+ //
267
+
268
+ }
269
+
270
+ func ExampleDevice_SetPIN() {
271
+ if os.Getenv("FIDO2_EXAMPLES_SET_PIN") != "1" {
272
+ return
273
+ }
274
+ libfido2.SetLogger(libfido2.NewLogger(libfido2.DebugLevel))
275
+
276
+ locs, err := libfido2.DeviceLocations()
277
+ if err != nil {
278
+ log.Fatal(err)
279
+ }
280
+ if len(locs) == 0 {
281
+ log.Println("No devices")
282
+ return
283
+ }
284
+
285
+ log.Printf("Using device: %+v\n", locs[0])
286
+ path := locs[0].Path
287
+ device, err := libfido2.NewDevice(path)
288
+ if err != nil {
289
+ log.Fatal(err)
290
+ }
291
+
292
+ pin := "12345"
293
+ if err := device.SetPIN(pin, ""); err != nil {
294
+ log.Fatal(err)
295
+ }
296
+
297
+ // Output:
298
+ //
299
+ }
300
+
301
+ func ExampleDevice_MakeCredential_hmacSecret() {
302
+ if os.Getenv("FIDO2_EXAMPLES") != "1" {
303
+ return
304
+ }
305
+ locs, err := libfido2.DeviceLocations()
306
+ if err != nil {
307
+ log.Fatal(err)
308
+ }
309
+ if len(locs) == 0 {
310
+ log.Fatal("No devices")
311
+ return
312
+ }
313
+
314
+ log.Printf("Using device: %+v\n", locs[0])
315
+ path := locs[0].Path
316
+ device, err := libfido2.NewDevice(path)
317
+ if err != nil {
318
+ log.Fatal(err)
319
+ }
320
+
321
+ cdh := bytes.Repeat([]byte{0x01}, 32)
322
+ rpID := "keys.pub"
323
+ pin := "12345"
324
+
325
+ attest, err := device.MakeCredential(
326
+ cdh,
327
+ libfido2.RelyingParty{
328
+ ID: rpID,
329
+ Name: "hmac-secret",
330
+ },
331
+ libfido2.User{
332
+ ID: libfido2.RandBytes(16),
333
+ Name: "hmac-secret",
334
+ },
335
+ libfido2.ES256, // Algorithm
336
+ pin,
337
+ &libfido2.MakeCredentialOpts{
338
+ Extensions: []libfido2.Extension{libfido2.HMACSecretExtension},
339
+ RK: libfido2.True,
340
+ // UV: libfido2.True,
341
+ // CredProtect: libfido2.CredProtectUVRequired,
342
+ },
343
+ )
344
+ if err != nil {
345
+ log.Fatal(err)
346
+ }
347
+
348
+ log.Printf("Credential ID: %s\n", hex.EncodeToString(attest.CredentialID))
349
+ }
350
+
351
+ type testVector struct {
352
+ CredentialID string
353
+ Secret string
354
+ }
355
+
356
+ func ExampleDevice_Assertion_hmacSecret() {
357
+ if os.Getenv("FIDO2_EXAMPLES") != "1" {
358
+ return
359
+ }
360
+ locs, err := libfido2.DeviceLocations()
361
+ if err != nil {
362
+ log.Fatal(err)
363
+ }
364
+ if len(locs) == 0 {
365
+ log.Fatalf("No devices")
366
+ return
367
+ }
368
+ log.Printf("Using device: %+v\n", locs[0])
369
+ path := locs[0].Path
370
+ device, err := libfido2.NewDevice(path)
371
+ if err != nil {
372
+ log.Fatal(err)
373
+ }
374
+
375
+ name := locs[0].Product + "/" + locs[0].Manufacturer
376
+
377
+ cdh := bytes.Repeat([]byte{0x01}, 32)
378
+ rpID := "keys.pub"
379
+ pin := "12345"
380
+
381
+ testVectors := map[string]testVector{
382
+ "SoloKey 4.0/SoloKeys": testVector{
383
+ CredentialID: "91874f4c3d580370bf5b5301130ecc034f5927d955f5399ebad267f5666c78598942d489f10d4f4780fad392eb2962d065bdd3574375e80c42218dadd199ed3ffe7deb010000",
384
+ Secret: "dd67d3aa73b13b7bb71ad0fe13cf8a247632a3508d7c9906ef6dc823906c3103",
385
+ },
386
+ "Security Key by Yubico/Yubico": testVector{
387
+ CredentialID: "c4fe75012ed137a0afcaa59ab36f0722b9b05849b2203fc4ba4f304033015eaafdbee823ee42dce88b4ae4d943926de3cc93e797004d108ed2465c675ae568e6",
388
+ Secret: "f3d37d52ca7a12cf05c34bd3c13ddc3288b723018697347e6ac5ea79b7d3cc83",
389
+ },
390
+ }
391
+
392
+ testVector, ok := testVectors[name]
393
+ if !ok {
394
+ log.Fatalf("No test vector found for %s", name)
395
+ }
396
+
397
+ credentialID, err := hex.DecodeString(testVector.CredentialID)
398
+ if err != nil {
399
+ log.Fatal(err)
400
+ }
401
+ salt := bytes.Repeat([]byte{0x02}, 32)
402
+
403
+ assertion, err := device.Assertion(
404
+ rpID,
405
+ cdh,
406
+ [][]byte{credentialID},
407
+ pin,
408
+ &libfido2.AssertionOpts{
409
+ Extensions: []libfido2.Extension{libfido2.HMACSecretExtension},
410
+ // UP: libfido2.True, // Required for some devices
411
+ // UV: libfido2.True, // Required for some devices
412
+ HMACSalt: salt,
413
+ },
414
+ )
415
+ if err != nil {
416
+ log.Fatal(err)
417
+ }
418
+
419
+ if testVector.Secret != hex.EncodeToString(assertion.HMACSecret) {
420
+ log.Fatalf("Expected %s", testVector.Secret)
421
+ }
422
+ }
423
+
424
+ func ExampleDevice_DeleteCredential() {
425
+ if os.Getenv("FIDO2_EXAMPLES") != "1" {
426
+ return
427
+ }
428
+ locs, err := libfido2.DeviceLocations()
429
+ if err != nil {
430
+ log.Fatal(err)
431
+ }
432
+ if len(locs) == 0 {
433
+ log.Fatal("No devices")
434
+ return
435
+ }
436
+
437
+ log.Printf("Using device: %+v\n", locs[0])
438
+ path := locs[0].Path
439
+ device, err := libfido2.NewDevice(path)
440
+ if err != nil {
441
+ log.Fatal(err)
442
+ }
443
+
444
+ pin := "12345"
445
+
446
+ info, err := device.CredentialsInfo(pin)
447
+ if err != nil {
448
+ log.Fatal(err)
449
+ }
450
+ log.Printf("Info: %+v\n", info)
451
+
452
+ rps, err := device.RelyingParties(pin)
453
+ if err != nil {
454
+ log.Fatal(err)
455
+ }
456
+ for _, rp := range rps {
457
+ creds, err := device.Credentials(rp.ID, pin)
458
+ if err != nil {
459
+ log.Fatal(err)
460
+ }
461
+ for _, cred := range creds {
462
+ log.Printf("Deleting: %s\n", hex.EncodeToString(cred.ID))
463
+ if err := device.DeleteCredential(cred.ID, pin); err != nil {
464
+ log.Fatal(err)
465
+ }
466
+ }
467
+ }
468
+
469
+ // Output:
470
+ //
471
+ }
472
+
473
+ func ExampleDevice_BioEnrollment() {
474
+ if os.Getenv("FIDO2_EXAMPLES") != "1" {
475
+ return
476
+ }
477
+ locs, err := libfido2.DeviceLocations()
478
+ if err != nil {
479
+ log.Fatal(err)
480
+ }
481
+ if len(locs) == 0 {
482
+ log.Fatal("No devices")
483
+ return
484
+ }
485
+
486
+ log.Printf("Using device: %+v\n", locs[0])
487
+ path := locs[0].Path
488
+ device, err := libfido2.NewDevice(path)
489
+ if err != nil {
490
+ log.Fatal(err)
491
+ }
492
+
493
+ pin := "12345"
494
+
495
+ err = device.BioEnroll(pin)
496
+ if err != nil {
497
+ log.Fatal(err)
498
+ }
499
+
500
+ // Output:
501
+ //
502
+ }
503
+
504
+ func ExampleDevice_BioList() {
505
+ if os.Getenv("FIDO2_EXAMPLES") != "1" {
506
+ return
507
+ }
508
+ locs, err := libfido2.DeviceLocations()
509
+ if err != nil {
510
+ log.Fatal(err)
511
+ }
512
+ if len(locs) == 0 {
513
+ log.Fatal("No devices")
514
+ return
515
+ }
516
+
517
+ log.Printf("Using device: %+v\n", locs[0])
518
+ path := locs[0].Path
519
+ device, err := libfido2.NewDevice(path)
520
+ if err != nil {
521
+ log.Fatal(err)
522
+ }
523
+
524
+ pin := "12345"
525
+
526
+ templates, err := device.BioList(pin)
527
+ if err != nil {
528
+ log.Fatal(err)
529
+ }
530
+
531
+ log.Println(templates)
532
+
533
+ // Output:
534
+ //
535
+ }
536
+
537
+ func ExampleDevice_BioDelete() {
538
+ if os.Getenv("FIDO2_EXAMPLES") != "1" {
539
+ return
540
+ }
541
+ locs, err := libfido2.DeviceLocations()
542
+ if err != nil {
543
+ log.Fatal(err)
544
+ }
545
+ if len(locs) == 0 {
546
+ log.Fatal("No devices")
547
+ return
548
+ }
549
+
550
+ log.Printf("Using device: %+v\n", locs[0])
551
+ path := locs[0].Path
552
+ device, err := libfido2.NewDevice(path)
553
+ if err != nil {
554
+ log.Fatal(err)
555
+ }
556
+
557
+ pin := "12345"
558
+
559
+ templates, err := device.BioList(pin)
560
+ if err != nil {
561
+ log.Fatal(err)
562
+ }
563
+
564
+ for _, template := range templates {
565
+ err := device.BioDelete(pin, template.ID)
566
+ if err != nil {
567
+ log.Fatal(err)
568
+ }
569
+ }
570
+
571
+ // Output:
572
+ //
573
+ }
574
+
575
+ func ExampleDevice_BioSetTemplateName() {
576
+ if os.Getenv("FIDO2_EXAMPLES") != "1" {
577
+ return
578
+ }
579
+ locs, err := libfido2.DeviceLocations()
580
+ if err != nil {
581
+ log.Fatal(err)
582
+ }
583
+ if len(locs) == 0 {
584
+ log.Fatal("No devices")
585
+ return
586
+ }
587
+
588
+ log.Printf("Using device: %+v\n", locs[0])
589
+ path := locs[0].Path
590
+ device, err := libfido2.NewDevice(path)
591
+ if err != nil {
592
+ log.Fatal(err)
593
+ }
594
+
595
+ pin := "12345"
596
+
597
+ templates, err := device.BioList(pin)
598
+ if err != nil {
599
+ log.Fatal(err)
600
+ }
601
+
602
+ if len(templates) == 0 {
603
+ log.Fatal("no bio template")
604
+ return
605
+ }
606
+
607
+ template := templates[0]
608
+ newName := "newName"
609
+
610
+ device.BioSetTemplateName(pin, template.ID, newName)
611
+
612
+ // Output:
613
+ //
614
+ }