### Credential Management - Get Metadata Source: https://context7.com/go-ctap/ctaphid/llms.txt Retrieves metadata about credential storage, including the number of existing resident credentials and the remaining capacity. Requires an authentication token. ```go package main import ( "fmt" "github.com/go-ctap/ctaphid/pkg/ctaptypes" "github.com/go-ctap/ctaphid/pkg/sugar" ) func main() { dev, err := sugar.SelectDevice() if err != nil { panic(err) } defer dev.Close() token, err := dev.GetPinUvAuthTokenUsingPIN( "12345678", ctaptypes.PermissionCredentialManagement, "", ) if err != nil { panic(err) } metadata, err := dev.GetCredsMetadata(token) if err != nil { panic(err) } fmt.Printf("Existing passkeys: %d\n", metadata.ExistingResidentCredentialsCount) fmt.Printf("Remaining capacity: %d\n", metadata.MaxPossibleRemainingResidentCredentialsCount) // Output: Existing passkeys: 5 // Output: Remaining capacity: 20 } ``` -------------------------------- ### Get PIN/UV Auth Token Using PIN Source: https://context7.com/go-ctap/ctaphid/llms.txt Obtains an authentication token using a provided PIN and specifies permissions for credential management. This token is necessary for subsequent authenticated operations. ```go package main import ( "fmt" "github.com/go-ctap/ctaphid/pkg/ctaptypes" "github.com/go-ctap/ctaphid/pkg/sugar" ) func main() { dev, err := sugar.SelectDevice() if err != nil { panic(err) } defer dev.Close() // Get token with credential management permission token, err := dev.GetPinUvAuthTokenUsingPIN( "12345678", // PIN ctaptypes.PermissionCredentialManagement, // Permission flags "", // RPID (optional, for some permissions) ) if err != nil { panic(err) } fmt.Printf("Obtained token of length: %d bytes\n", len(token)) // Use token for subsequent authenticated operations } ``` -------------------------------- ### Get PIN/UV Auth Token Using Biometrics Source: https://context7.com/go-ctap/ctaphid/llms.txt Obtains an authentication token using biometric verification. This method requires the device to have biometric enrollment configured. It supports multiple permission flags. ```go package main import ( "fmt" "github.com/go-ctap/ctaphid/pkg/ctaptypes" "github.com/go-ctap/ctaphid/pkg/sugar" ) func main() { dev, err := sugar.SelectDevice() if err != nil { panic(err) } defer dev.Close() // Get token using biometric verification token, err := dev.GetPinUvAuthTokenUsingUV( ctaptypes.PermissionMakeCredential|ctaptypes.PermissionGetAssertion, "example.com", // RPID ) if err != nil { // ErrUvNotConfigured if biometrics not enrolled panic(err) } fmt.Printf("Obtained UV token of length: %d bytes\n", len(token)) } ``` -------------------------------- ### Get Fingerprint Sensor Info in Go Source: https://context7.com/go-ctap/ctaphid/llms.txt Retrieves information about the authenticator's fingerprint sensor, including its type (touch or swipe) and the number of samples required for enrollment. Useful for understanding device capabilities. ```go package main import ( "fmt" "github.com/go-ctap/ctaphid/pkg/sugar" ) func main() { dev, err := sugar.SelectDevice() if err != nil { panic(err) } defer dev.Close() // Get fingerprint sensor information sensorInfo, err := dev.GetFingerprintSensorInfo() if err != nil { panic(err) } kindStr := "touch" if sensorInfo.FingerprintKind == 2 { kindStr = "swipe" } fmt.Printf("Fingerprint sensor type: %s\n", kindStr) fmt.Printf("Samples required for enrollment: %d\n", sensorInfo.MaxCaptureSamplesRequiredForEnroll) fmt.Printf("Max friendly name length: %d\n", sensorInfo.MaxTemplateFriendlyName) } ``` -------------------------------- ### Get Assertion (WebAuthn Authentication) in Go Source: https://context7.com/go-ctap/ctaphid/llms.txt Use this to retrieve an assertion from stored credentials for authentication. It returns an iterator for handling multiple matching credentials, particularly useful for discoverable credential flows. ```go package main import ( "fmt" "github.com/go-ctap/ctaphid/pkg/ctaptypes" "github.com/go-ctap/ctaphid/pkg/sugar" "github.com/go-ctap/ctaphid/pkg/webauthntypes" ) func main() { dev, err := sugar.SelectDevice() if err != nil { panic(err) } defer dev.Close() token, err := dev.GetPinUvAuthTokenUsingPIN( "12345678", ctaptypes.PermissionGetAssertion, "example.com", ) if err != nil { panic(err) } // Client data (normally provided by the browser/client) clientData := []byte(`{"type":"webauthn.get","challenge":"...","origin":"https://example.com"}`) // Get assertion (discoverable credential flow) for assertion, err := range dev.GetAssertion( token, "example.com", // RPID clientData, nil, // allowList (nil for discoverable credentials) nil, // extensions map[ctaptypes.Option]bool{ ctaptypes.OptionUserPresence: true, ctaptypes.OptionUserVerification: true, }, ) { if err != nil { panic(err) } fmt.Printf("Assertion received\n") fmt.Printf("User ID: %s\n", string(assertion.User.ID)) fmt.Printf("Signature: %x\n", assertion.Signature[:16]) fmt.Printf("Auth Data flags: %08b\n", assertion.AuthData.Flags) break // Use first assertion } } ``` -------------------------------- ### Connect to Device by Path Source: https://context7.com/go-ctap/ctaphid/llms.txt Enumerates available devices and connects to a specific one using its HID path. ```go package main import ( "fmt" "github.com/go-ctap/ctaphid/pkg/device" "github.com/go-ctap/ctaphid/pkg/options" "github.com/go-ctap/ctaphid/pkg/sugar" ) func main() { // First, enumerate available FIDO devices devInfos, err := sugar.EnumerateFIDODevices() if err != nil { panic(err) } for _, info := range devInfos { fmt.Printf("Found device: %s (path: %s)\n", info.Product, info.Path) } // Connect to a specific device by path if len(devInfos) > 0 { dev, err := device.New(devInfos[0].Path, options.WithLogger(nil)) if err != nil { panic(err) } defer dev.Close() fmt.Printf("Connected to device at: %s\n", dev.Path) } } ``` -------------------------------- ### Execute Factory Reset in Go Source: https://context7.com/go-ctap/ctaphid/llms.txt Erases all credentials and settings from the authenticator. Must be executed within 10 seconds of device connection. ```go package main import ( "fmt" "github.com/go-ctap/ctaphid/pkg/sugar" ) func main() { // IMPORTANT: Connect device and run immediately (within 10 seconds) dev, err := sugar.SelectDevice() if err != nil { panic(err) } defer dev.Close() fmt.Println("WARNING: This will erase all credentials!") fmt.Println("Touch the device to confirm reset...") err = dev.Reset() if err != nil { panic(err) } fmt.Println("Device reset complete - all data erased") } ``` -------------------------------- ### Set Initial Device PIN Source: https://context7.com/go-ctap/ctaphid/llms.txt Configures a new PIN on a device that does not currently have one set. ```go package main import ( "fmt" "github.com/go-ctap/ctaphid/pkg/sugar" ) func main() { dev, err := sugar.SelectDevice() if err != nil { panic(err) } defer dev.Close() // Check if PIN is already set info := dev.GetInfo() if clientPin, ok := info.Options["clientPin"]; ok && clientPin { fmt.Println("PIN is already set, use ChangePIN instead") return } // Set a new PIN (minimum 4 characters) err = dev.SetPIN("12345678") if err != nil { panic(err) } fmt.Println("PIN set successfully") } ``` -------------------------------- ### Credential Management - Enumerate Relying Parties and Credentials Source: https://context7.com/go-ctap/ctaphid/llms.txt Lists all stored credentials by iterating through relying parties and their associated credentials. Uses Go iterators for efficient memory usage and requires an authentication token. ```go package main import ( "fmt" "github.com/go-ctap/ctaphid/pkg/ctaptypes" "github.com/go-ctap/ctaphid/pkg/sugar" ) func main() { dev, err := sugar.SelectDevice() if err != nil { panic(err) } defer dev.Close() token, err := dev.GetPinUvAuthTokenUsingPIN( "12345678", ctaptypes.PermissionCredentialManagement, "", ) if err != nil { panic(err) } // Collect all relying parties rps := make([]*ctaptypes.AuthenticatorCredentialManagementResponse, 0) for rp, err := range dev.EnumerateRPs(token) { if err != nil { panic(err) } rps = append(rps, rp) } // Enumerate credentials for each RP for i, rp := range rps { fmt.Printf("\nRP %d: %s\n", i+1, rp.RP.ID) for cred, err := range dev.EnumerateCredentials(token, rp.RPIDHash) { if err != nil { panic(err) } fmt.Printf(" - User ID: %s\n", string(cred.User.ID)) fmt.Printf(" Name: %s\n", cred.User.Name) fmt.Printf(" Display Name: %s\n", cred.User.DisplayName) fmt.Printf(" Credential ID: %x\n", cred.CredentialID.ID[:8]) } } } ``` -------------------------------- ### Perform Ping and Wink Transport Commands in Go Source: https://context7.com/go-ctap/ctaphid/llms.txt Executes echo tests and triggers device LED indicators. Wink support is optional and may not be available on all hardware. ```go package main import ( "fmt" "github.com/go-ctap/ctaphid/pkg/sugar" ) func main() { dev, err := sugar.SelectDevice() if err != nil { panic(err) } defer dev.Close() // Ping the device (echo test) pingData := []byte("hello authenticator") err = dev.Ping(pingData) if err != nil { panic(err) } fmt.Println("Ping successful - device is responsive") // Wink the device (LED blink) err = dev.Wink() if err != nil { // Wink is optional, some devices don't support it fmt.Printf("Wink not supported: %v\n", err) } else { fmt.Println("Device LED should be blinking") } } ``` -------------------------------- ### Make Credential (WebAuthn Registration) in Go Source: https://context7.com/go-ctap/ctaphid/llms.txt Use this to create a new credential on an authenticator, essential for WebAuthn/FIDO2 registration. Ensure you have a valid PIN and origin. ```go package main import ( "fmt" "github.com/go-ctap/ctaphid/pkg/ctaptypes" "github.com/go-ctap/ctaphid/pkg/sugar" "github.com/go-ctap/ctaphid/pkg/webauthntypes" ) func main() { dev, err := sugar.SelectDevice() if err != nil { panic(err) } defer dev.Close() token, err := dev.GetPinUvAuthTokenUsingPIN( "12345678", ctaptypes.PermissionMakeCredential, "example.com", ) if err != nil { panic(err) } // Client data (normally provided by the browser/client) clientData := []byte(`{"type":"webauthn.create","challenge":"...","origin":"https://example.com"}`) resp, err := dev.MakeCredential( token, clientData, webauthntypes.PublicKeyCredentialRpEntity{ ID: "example.com", Name: "Example Site", }, webauthntypes.PublicKeyCredentialUserEntity{ ID: []byte("user-unique-id-123"), Name: "user@example.com", DisplayName: "John Doe", }, []webauthntypes.PublicKeyCredentialParameters{ {Type: "public-key", Alg: -7}, // ES256 {Type: "public-key", Alg: -257}, // RS256 }, nil, // excludeList nil, // extensions map[ctaptypes.Option]bool{ ctaptypes.OptionResidentKeys: true, // Create discoverable credential ctaptypes.OptionUserVerification: true, }, 0, // enterpriseAttestation nil, // attestationFormatsPreference ) if err != nil { panic(err) } fmt.Printf("Credential created successfully\n") fmt.Printf("Credential ID: %x\n", resp.AuthData.AttestedCredentialData.CredentialID) fmt.Printf("Public Key Algorithm: %d\n", resp.AuthData.AttestedCredentialData.CredentialPublicKey.Alg()) } ``` -------------------------------- ### Store and Retrieve Large Blobs with Go CTAPHID Source: https://context7.com/go-ctap/ctaphid/llms.txt Demonstrates how to store and retrieve arbitrary data using the Large Blobs feature of a FIDO authenticator. It first checks for device support, then retrieves existing blobs, and finally stores new ones. Storing requires write permissions and a valid authentication token. ```go package main import ( "fmt" "github.com/go-ctap/ctaphid/pkg/ctaptypes" "github.com/go-ctap/ctaphid/pkg/sugar" ) func main() { dev, err := sugar.SelectDevice() if err != nil { panic(err) } defer dev.Close() // Check if device supports large blobs info := dev.GetInfo() if largeBlobs, ok := info.Options["largeBlobs"]; !ok || !largeBlobs { fmt.Println("Device doesn't support large blobs") return } // Read existing large blobs blobs, err := dev.GetLargeBlobs() if err != nil { panic(err) } fmt.Printf("Found %d large blob(s)\n", len(blobs)) // Store new large blobs (requires write permission) token, err := dev.GetPinUvAuthTokenUsingPIN( "12345678", ctaptypes.PermissionLargeBlobWrite, "", ) if err != nil { panic(err) } newBlobs := []*ctaptypes.LargeBlob{ { Ciphertext: []byte("encrypted-data-here"), Nonce: []byte("nonce-12-bytes"), OrigSize: 100, AssociatedDataHash: []byte("credential-id-hash"), }, } err = dev.SetLargeBlobs(token, newBlobs) if err != nil { panic(err) } fmt.Println("Large blobs stored successfully") } ``` -------------------------------- ### Configure Minimum PIN Length in Go Source: https://context7.com/go-ctap/ctaphid/llms.txt Sets the minimum PIN length requirement and forces a PIN change. Requires obtaining a PIN/UV auth token with configuration permissions first. ```go package main import ( "fmt" "github.com/go-ctap/ctaphid/pkg/ctaptypes" "github.com/go-ctap/ctaphid/pkg/sugar" ) func main() { dev, err := sugar.SelectDevice() if err != nil { panic(err) } defer dev.Close() token, err := dev.GetPinUvAuthTokenUsingPIN( "12345678", ctaptypes.PermissionAuthenticatorConfiguration, "", ) if err != nil { panic(err) } // Set minimum PIN length to 8 characters err = dev.SetMinPINLength( token, 8, // newMinPINLength []string{"example.com"}, // RPs that can see min PIN length true, // forceChangePin false, // pinComplexityPolicy ) if err != nil { panic(err) } fmt.Println("Minimum PIN length configured") } ``` -------------------------------- ### Select FIDO2 Device Source: https://context7.com/go-ctap/ctaphid/llms.txt Uses the sugar package to enumerate and select a FIDO2 device, prompting the user for physical presence. ```go package main import ( "fmt" "log/slog" "os" "github.com/go-ctap/ctaphid/pkg/options" "github.com/go-ctap/ctaphid/pkg/sugar" ) func main() { // Set up debug logging lvl := new(slog.LevelVar) lvl.Set(slog.LevelDebug) logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ Level: lvl, })) // Select a FIDO2 device (prompts user to touch their device) dev, err := sugar.SelectDevice( options.WithLogger(logger), // Use options.WithUseNamedPipes() for Windows virtual authenticators ) if err != nil { panic(err) } defer dev.Close() // Get device info info := dev.GetInfo() fmt.Printf("Device AAGUID: %x\n", info.AAGUID) fmt.Printf("Supported versions: %v\n", info.Versions) fmt.Printf("Supported extensions: %v\n", info.Extensions) } ``` -------------------------------- ### Enroll Fingerprint with Go CTAPHID Source: https://context7.com/go-ctap/ctaphid/llms.txt Initiates and completes a fingerprint enrollment process on a FIDO authenticator. Requires a PIN and specific permissions. The process is iterative, capturing multiple samples until enrollment is successful. ```go package main import ( "fmt" "github.com/go-ctap/ctaphid/pkg/ctaptypes" "github.com/go-ctap/ctaphid/pkg/sugar" ) func main() { dev, err := sugar.SelectDevice() if err != nil { panic(err) } defer dev.Close() token, err := dev.GetPinUvAuthTokenUsingPIN( "12345678", ctaptypes.PermissionBioEnrollment, "", ) if err != nil { panic(err) } // Begin enrollment (returns template ID and remaining samples) resp, err := dev.BeginEnroll(token, 30000) // 30 second timeout if err != nil { panic(err) } templateID := resp.TemplateID fmt.Printf("Enrollment started, template ID: %x\n", templateID) fmt.Printf("Status: %s, Remaining samples: %d\n", resp.LastEnrollSampleStatus, resp.RemainingSamples) // Continue capturing samples until complete for resp.RemainingSamples > 0 { fmt.Println("Please touch the sensor again...") resp, err = dev.EnrollCaptureNextSample(token, templateID, 30000) if err != nil { panic(err) } fmt.Printf("Status: %s, Remaining: %d\n", resp.LastEnrollSampleStatus, resp.RemainingSamples) } // Set a friendly name for the enrollment err = dev.SetFriendlyName(token, templateID, "Right Index Finger") if err != nil { panic(err) } fmt.Println("Fingerprint enrollment complete!") } ``` -------------------------------- ### List and Remove Fingerprint Enrollments with Go CTAPHID Source: https://context7.com/go-ctap/ctaphid/llms.txt Enumerates existing fingerprint enrollments on an authenticator and provides functionality to remove a specific template. Requires a PIN and appropriate permissions. The process involves fetching all enrollments and then targeting a specific one for removal. ```go package main import ( "fmt" "github.com/go-ctap/ctaphid/pkg/ctaptypes" "github.com/go-ctap/ctaphid/pkg/sugar" ) func main() { dev, err := sugar.SelectDevice() if err != nil { panic(err) } defer dev.Close() token, err := dev.GetPinUvAuthTokenUsingPIN( "12345678", ctaptypes.PermissionBioEnrollment, "", ) if err != nil { panic(err) } // List all fingerprint enrollments enrollments, err := dev.EnumerateEnrollments(token) if err != nil { panic(err) } fmt.Printf("Found %d fingerprint(s):\n", len(enrollments.TemplateInfos)) for i, tmpl := range enrollments.TemplateInfos { fmt.Printf(" %d. %s (ID: %x)\n", i+1, tmpl.FriendlyName, tmpl.TemplateID) } // Remove a specific enrollment if len(enrollments.TemplateInfos) > 0 { templateToRemove := enrollments.TemplateInfos[0].TemplateID err = dev.RemoveEnrollment(token, templateToRemove) if err != nil { panic(err) } fmt.Println("Enrollment removed successfully") } } ``` -------------------------------- ### Toggle Always UV Setting with Go CTAPHID Source: https://context7.com/go-ctap/ctaphid/llms.txt Toggles the 'always require user verification' (Always UV) setting on a FIDO authenticator. This operation requires a PIN and the Authenticator Configuration permission. It's a simple toggle that affects subsequent operations requiring user presence. ```go package main import ( "fmt" "github.com/go-ctap/ctaphid/pkg/ctaptypes" "github.com/go-ctap/ctaphid/pkg/sugar" ) func main() { dev, err := sugar.SelectDevice() if err != nil { panic(err) } defer dev.Close() token, err := dev.GetPinUvAuthTokenUsingPIN( "12345678", ctaptypes.PermissionAuthenticatorConfiguration, "", ) if err != nil { panic(err) } // Toggle the alwaysUv setting err = dev.ToggleAlwaysUV(token) if err != nil { panic(err) } fmt.Println("Always UV setting toggled") } ``` -------------------------------- ### Change Existing Device PIN Source: https://context7.com/go-ctap/ctaphid/llms.txt Updates an existing PIN to a new value, requiring the current PIN for authentication. ```go package main import ( "fmt" "github.com/go-ctap/ctaphid/pkg/sugar" ) func main() { dev, err := sugar.SelectDevice() if err != nil { panic(err) } defer dev.Close() // Change PIN from old value to new value err = dev.ChangePIN("12345678", "newSecurePin123") if err != nil { panic(err) } fmt.Println("PIN changed successfully") } ``` -------------------------------- ### Retrieve PIN Retry Count Source: https://context7.com/go-ctap/ctaphid/llms.txt Checks remaining PIN attempts and whether a power cycle is required to reset the counter. ```go package main import ( "fmt" "github.com/go-ctap/ctaphid/pkg/sugar" ) func main() { dev, err := sugar.SelectDevice() if err != nil { panic(err) } defer dev.Close() retries, powerCycleRequired, err := dev.GetPINRetries() if err != nil { panic(err) } fmt.Printf("PIN retries remaining: %d\n", retries) fmt.Printf("Power cycle required: %t\n", powerCycleRequired) // Output: PIN retries remaining: 8 // Output: Power cycle required: false } ``` -------------------------------- ### Credential Management - Delete Credential Source: https://context7.com/go-ctap/ctaphid/llms.txt Removes a specific credential from the authenticator by its credential ID. This operation requires an authentication token and involves iterating through existing credentials to find the one to delete. ```go package main import ( "fmt" "github.com/go-ctap/ctaphid/pkg/ctaptypes" "github.com/go-ctap/ctaphid/pkg/sugar" "github.com/go-ctap/ctaphid/pkg/webauthntypes" ) func main() { dev, err := sugar.SelectDevice() if err != nil { panic(err) } defer dev.Close() token, err := dev.GetPinUvAuthTokenUsingPIN( "12345678", ctaptypes.PermissionCredentialManagement, "", ) if err != nil { panic(err) } // Find and delete a specific credential for rp, err := range dev.EnumerateRPs(token) { if err != nil { panic(err) } for cred, err := range dev.EnumerateCredentials(token, rp.RPIDHash) { if err != nil { panic(err) } // Delete credentials matching criteria if cred.User.Name == "user@example.com" { err := dev.DeleteCredential(token, webauthntypes.PublicKeyCredentialDescriptor{ Type: "public-key", ID: cred.CredentialID.ID, }) if err != nil { panic(err) } fmt.Printf("Deleted credential for: %s\n", cred.User.Name) } } } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.