pwn 0.5.784 → 0.5.787
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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/Gemfile +6 -6
- data/README.md +37 -0
- data/bin/pwn +2 -1
- data/bin/pwn_web_cache_deception +35 -7
- data/build_gem.sh +1 -1
- data/documentation/AI-Integration.md +7 -5
- data/documentation/Agent-Tool-Registry.md +2 -2
- data/documentation/Backup-Retention.md +69 -15
- data/documentation/Configuration.md +10 -6
- data/documentation/Contributing.md +1 -1
- data/documentation/Cron.md +2 -2
- data/documentation/Diagrams.md +2 -2
- data/documentation/General-PWN-Usage.md +4 -3
- data/documentation/Harness-Evaluation.md +1 -1
- data/documentation/Home.md +6 -5
- data/documentation/How-PWN-Works.md +6 -5
- data/documentation/Installation.md +12 -9
- data/documentation/Mission-Cancellation.md +134 -0
- data/documentation/Operability.md +18 -0
- data/documentation/Persistence.md +7 -5
- data/documentation/Plugin-Degradation.md +14 -0
- data/documentation/Plugins.md +3 -2
- data/documentation/Policy-Benchmark.md +32 -33
- data/documentation/Runtime-Source-Protection.md +162 -0
- data/documentation/Transparent-Browser.md +11 -0
- data/documentation/Troubleshooting.md +3 -2
- data/documentation/What-is-PWN.md +2 -2
- data/documentation/YubiKey-Vaults.md +185 -0
- data/documentation/YubiKey.md +218 -0
- data/documentation/diagrams/cron-scheduling.svg +130 -130
- data/documentation/diagrams/dot/cron-scheduling.dot +3 -3
- data/documentation/diagrams/dot/persistence-filesystem.dot +5 -3
- data/documentation/diagrams/dot/plugin-ecosystem.dot +2 -2
- data/documentation/diagrams/dot/pwn-ai-feedback-learning-loop.dot +1 -1
- data/documentation/diagrams/dot/reinforcement-learning.dot +2 -2
- data/documentation/diagrams/persistence-filesystem.svg +172 -142
- data/documentation/diagrams/plugin-ecosystem.svg +64 -64
- data/documentation/diagrams/pwn-ai-feedback-learning-loop.svg +1 -1
- data/documentation/diagrams/reinforcement-learning.svg +89 -89
- data/documentation/pwn-ai-Agent.md +10 -4
- data/etc/default_cron/session_cleanup.rb +43 -27
- data/etc/default_skills/pwn/ai/agent/mission_namespace/SKILL.md +21 -0
- data/etc/default_skills/pwn/ai/agent/tools/browser_act/SKILL.md +45 -0
- data/etc/default_skills/pwn/ai/agent/tools/loot_query/SKILL.md +27 -26
- data/etc/default_skills/pwn/ai/agent/tools/recon_run/SKILL.md +25 -15
- data/etc/default_skills/pwn/ai/agent/tools/workspace_tool/SKILL.md +24 -0
- data/etc/default_skills/pwn/ai/server_tools/SKILL.md +25 -0
- data/etc/default_skills/pwn/backups/SKILL.md +54 -0
- data/etc/default_skills/pwn/plugins/recon/SKILL.md +12 -1
- data/etc/default_skills/pwn/plugins/yubikey/SKILL.md +157 -0
- data/etc/default_skills/pwn/plugins/yubikey/fido/SKILL.md +189 -0
- data/etc/default_skills/pwn/plugins/yubikey/hsmauth/SKILL.md +83 -0
- data/etc/default_skills/pwn/plugins/yubikey/management/SKILL.md +80 -0
- data/etc/default_skills/pwn/plugins/yubikey/oath/SKILL.md +115 -0
- data/etc/default_skills/pwn/plugins/yubikey/openpgp/SKILL.md +144 -0
- data/etc/default_skills/pwn/plugins/yubikey/otp/SKILL.md +97 -0
- data/etc/default_skills/pwn/plugins/yubikey/piv/SKILL.md +110 -0
- data/etc/default_skills/pwn/plugins/yubikey/protocol/SKILL.md +21 -0
- data/etc/default_skills/pwn/plugins/yubikey/security_domain/SKILL.md +75 -0
- data/etc/default_skills/pwn/plugins/yubikey/security_domain/scp/SKILL.md +46 -0
- data/etc/default_skills/pwn/plugins/yubikey/transport/SKILL.md +98 -0
- data/etc/default_skills/pwn/redaction/SKILL.md +13 -1
- data/lib/pwn/ai/agent/dispatch.rb +26 -15
- data/lib/pwn/ai/agent/learning.rb +14 -18
- data/lib/pwn/ai/agent/loop.rb +17 -1
- data/lib/pwn/ai/agent/mission_namespace.rb +331 -0
- data/lib/pwn/ai/agent/policy_evaluation.rb +334 -36
- data/lib/pwn/ai/agent/prompt_builder.rb +13 -2
- data/lib/pwn/ai/agent/request_runtime.rb +122 -18
- data/lib/pwn/ai/agent/reward.rb +5 -3
- data/lib/pwn/ai/agent/skill_consolidation.rb +3 -2
- data/lib/pwn/ai/agent/skill_review.rb +9 -5
- data/lib/pwn/ai/agent/swarm.rb +4 -0
- data/lib/pwn/ai/agent/tools/browser_act.rb +32 -0
- data/lib/pwn/ai/agent/tools/loot_query.rb +11 -1
- data/lib/pwn/ai/agent/tools/recon_run.rb +11 -1
- data/lib/pwn/ai/agent/tools/workspace_tool.rb +29 -0
- data/lib/pwn/ai/agent/turn_finalizer.rb +6 -2
- data/lib/pwn/ai/agent.rb +1 -0
- data/lib/pwn/ai/anthropic.rb +8 -33
- data/lib/pwn/ai/cli.rb +34 -5
- data/lib/pwn/ai/gemini.rb +1 -0
- data/lib/pwn/ai/grok.rb +39 -28
- data/lib/pwn/ai/ollama.rb +4 -2
- data/lib/pwn/ai/open_ai.rb +11 -32
- data/lib/pwn/ai/open_web_ui.rb +62 -4
- data/lib/pwn/ai/router.rb +8 -1
- data/lib/pwn/ai/server_tools.rb +231 -0
- data/lib/pwn/ai.rb +1 -0
- data/lib/pwn/backups.rb +349 -0
- data/lib/pwn/config.rb +70 -39
- data/lib/pwn/migrate.rb +85 -280
- data/lib/pwn/module_skills.rb +7 -0
- data/lib/pwn/plugins/ai_sandbox.rb +538 -1
- data/lib/pwn/plugins/authentication_helper.rb +74 -4
- data/lib/pwn/plugins/basic_auth.rb +2 -1
- data/lib/pwn/plugins/google_workspace.rb +4 -21
- data/lib/pwn/plugins/jobs.rb +1 -1
- data/lib/pwn/plugins/log.rb +3 -1
- data/lib/pwn/plugins/preflight_checker.rb +34 -9
- data/lib/pwn/plugins/recon.rb +4 -1
- data/lib/pwn/plugins/repl/ai.rb +293 -26
- data/lib/pwn/plugins/repl/ai_console.rb +268 -88
- data/lib/pwn/plugins/repl/ai_swarm.rb +177 -58
- data/lib/pwn/plugins/repl/mesh.rb +14 -19
- data/lib/pwn/plugins/repl/vault.rb +4 -15
- data/lib/pwn/plugins/repl.rb +9 -216
- data/lib/pwn/plugins/sandbox/driver.rb +4 -0
- data/lib/pwn/plugins/transparent_browser.rb +215 -0
- data/lib/pwn/plugins/vault.rb +412 -135
- data/lib/pwn/plugins/yubikey/fido.rb +1288 -0
- data/lib/pwn/plugins/yubikey/hsmauth.rb +439 -0
- data/lib/pwn/plugins/yubikey/management.rb +686 -0
- data/lib/pwn/plugins/yubikey/oath.rb +766 -0
- data/lib/pwn/plugins/yubikey/openpgp.rb +1063 -0
- data/lib/pwn/plugins/yubikey/otp.rb +897 -0
- data/lib/pwn/plugins/yubikey/piv.rb +1315 -0
- data/lib/pwn/plugins/yubikey/protocol.rb +341 -0
- data/lib/pwn/plugins/yubikey/security_domain/scp.rb +482 -0
- data/lib/pwn/plugins/yubikey/security_domain.rb +464 -0
- data/lib/pwn/plugins/yubikey/transport.rb +1017 -0
- data/lib/pwn/plugins/yubikey.rb +844 -0
- data/lib/pwn/plugins.rb +1 -0
- data/lib/pwn/redaction.rb +69 -12
- data/lib/pwn/session_trace.rb +4 -0
- data/lib/pwn/setup.rb +114 -24
- data/lib/pwn/version.rb +1 -1
- data/lib/pwn/www/app_cobalt_io.rb +16 -5
- data/lib/pwn/www/bug_crowd.rb +16 -5
- data/lib/pwn/www/coinbase_pro.rb +16 -5
- data/lib/pwn/www/github.rb +30 -14
- data/lib/pwn/www/paypal.rb +15 -4
- data/lib/pwn/www/synack.rb +16 -5
- data/lib/pwn/www/twitter.rb +17 -6
- data/lib/pwn.rb +1 -0
- data/spec/documentation/installation_md_spec.rb +1 -1
- data/spec/fixtures/yubikey/apdu_frames.json +162 -0
- data/spec/integration/authentication_helper_oath_spec.rb +117 -0
- data/spec/integration/controller_spill_spec.rb +48 -0
- data/spec/integration/harness_process_spec.rb +97 -0
- data/spec/integration/mission_cancel_spec.rb +79 -0
- data/spec/integration/mission_curses_pty_spec.rb +44 -0
- data/spec/integration/readme_security_spec.rb +47 -0
- data/spec/integration/web_cache_deception_yubikey_spec.rb +159 -0
- data/spec/lib/pwn/ai/agent/dispatch_spec.rb +6 -3
- data/spec/lib/pwn/ai/agent/dispatch_vault_safety_spec.rb +86 -0
- data/spec/lib/pwn/ai/agent/injection_guard_spec.rb +2 -0
- data/spec/lib/pwn/ai/agent/learning_spec.rb +4 -4
- data/spec/lib/pwn/ai/agent/loop_artifacts_spec.rb +5 -0
- data/spec/lib/pwn/ai/agent/loop_spec.rb +104 -29
- data/spec/lib/pwn/ai/agent/mission_namespace_spec.rb +138 -0
- data/spec/lib/pwn/ai/agent/policy_evaluation_spec.rb +10 -23
- data/spec/lib/pwn/ai/agent/request_runtime_spec.rb +48 -0
- data/spec/lib/pwn/ai/agent/shell_search_effect_spec.rb +44 -0
- data/spec/lib/pwn/ai/agent/solve_spec.rb +6 -4
- data/spec/lib/pwn/ai/agent/tools/browser_act_spec.rb +44 -0
- data/spec/lib/pwn/ai/agent/tools/loot_query_yubikey_spec.rb +55 -0
- data/spec/lib/pwn/ai/agent/tools/recon_run_yubikey_spec.rb +43 -0
- data/spec/lib/pwn/ai/agent/tools/workspace_tool_spec.rb +20 -0
- data/spec/lib/pwn/ai/agent/turn_finalizer_spec.rb +7 -0
- data/spec/lib/pwn/ai/anthropic_vault_enrollment_spec.rb +37 -0
- data/spec/lib/pwn/ai/cli_spec.rb +8 -16
- data/spec/lib/pwn/ai/oauth_vault_persistence_spec.rb +195 -0
- data/spec/lib/pwn/ai/open_ai_spec.rb +2 -2
- data/spec/lib/pwn/ai/open_web_ui_workspace_spec.rb +36 -0
- data/spec/lib/pwn/ai/router_spec.rb +1 -1
- data/spec/lib/pwn/ai/server_tools_spec.rb +39 -0
- data/spec/lib/pwn/backups_spec.rb +129 -0
- data/spec/lib/pwn/config_redaction_yubikey_spec.rb +28 -0
- data/spec/lib/pwn/config_yubikey_spec.rb +92 -0
- data/spec/lib/pwn/migrate_spec.rb +29 -81
- data/spec/lib/pwn/migrate_yubikey_spec.rb +128 -0
- data/spec/lib/pwn/module_skills_spec.rb +8 -0
- data/spec/lib/pwn/plugins/ai_sandbox_spec.rb +230 -0
- data/spec/lib/pwn/plugins/authentication_helper_native_yubikey_spec.rb +40 -0
- data/spec/lib/pwn/plugins/authentication_helper_yubikey_spec.rb +90 -0
- data/spec/lib/pwn/plugins/capability_broker/daemon_spec.rb +1 -1
- data/spec/lib/pwn/plugins/google_workspace_spec.rb +17 -35
- data/spec/lib/pwn/plugins/log_yubikey_spec.rb +47 -0
- data/spec/lib/pwn/plugins/preflight_checker_native_yubikey_spec.rb +19 -0
- data/spec/lib/pwn/plugins/preflight_checker_yubikey_spec.rb +55 -0
- data/spec/lib/pwn/plugins/recon_yubikey_spec.rb +43 -0
- data/spec/lib/pwn/plugins/repl/ai_console_spec.rb +110 -75
- data/spec/lib/pwn/plugins/repl/ai_legacy_containment_spec.rb +200 -0
- data/spec/lib/pwn/plugins/repl/ai_swarm_spec.rb +19 -16
- data/spec/lib/pwn/plugins/repl/ai_vault_edit_yubikey_spec.rb +103 -0
- data/spec/lib/pwn/plugins/repl/ai_yubikey_spec.rb +48 -0
- data/spec/lib/pwn/plugins/repl/mesh_vault_persistence_spec.rb +149 -0
- data/spec/lib/pwn/plugins/repl/vault_yaml_serialization_spec.rb +11 -0
- data/spec/lib/pwn/plugins/repl/vault_yubikey_spec.rb +39 -0
- data/spec/lib/pwn/plugins/repl_mesh_layout_spec.rb +2 -0
- data/spec/lib/pwn/plugins/repl_spec.rb +56 -5
- data/spec/lib/pwn/plugins/transparent_browser_jev_spec.rb +46 -0
- data/spec/lib/pwn/plugins/vault_native_yubikey_spec.rb +29 -0
- data/spec/lib/pwn/plugins/vault_publication_safety_spec.rb +258 -0
- data/spec/lib/pwn/plugins/vault_store_safety_spec.rb +241 -0
- data/spec/lib/pwn/plugins/vault_yubikey_safety_spec.rb +168 -0
- data/spec/lib/pwn/plugins/vault_yubikey_spec.rb +128 -0
- data/spec/lib/pwn/plugins/vault_yubikey_vector_spec.rb +45 -0
- data/spec/lib/pwn/plugins/yubikey/fido_spec.rb +854 -0
- data/spec/lib/pwn/plugins/yubikey/hsmauth_spec.rb +235 -0
- data/spec/lib/pwn/plugins/yubikey/management_spec.rb +277 -0
- data/spec/lib/pwn/plugins/yubikey/oath_spec.rb +349 -0
- data/spec/lib/pwn/plugins/yubikey/openpgp_spec.rb +810 -0
- data/spec/lib/pwn/plugins/yubikey/otp_spec.rb +337 -0
- data/spec/lib/pwn/plugins/yubikey/piv_spec.rb +646 -0
- data/spec/lib/pwn/plugins/yubikey/protocol_secure_spec.rb +28 -0
- data/spec/lib/pwn/plugins/yubikey/protocol_spec.rb +149 -0
- data/spec/lib/pwn/plugins/yubikey/protocol_vectors_spec.rb +18 -0
- data/spec/lib/pwn/plugins/yubikey/security_domain/scp_spec.rb +256 -0
- data/spec/lib/pwn/plugins/yubikey/security_domain/support.rb +153 -0
- data/spec/lib/pwn/plugins/yubikey/security_domain_spec.rb +296 -0
- data/spec/lib/pwn/plugins/yubikey/transport_spec.rb +760 -0
- data/spec/lib/pwn/plugins/yubikey_security_spec.rb +260 -0
- data/spec/lib/pwn/plugins/yubikey_spec.rb +209 -0
- data/spec/lib/pwn/plugins/yubikey_terminal_spec.rb +147 -0
- data/spec/lib/pwn/redaction_yubikey_spec.rb +61 -0
- data/spec/lib/pwn/session_cleanup_default_spec.rb +7 -5
- data/spec/lib/pwn/session_cleanup_payload_spec.rb +11 -11
- data/spec/lib/pwn/session_cleanup_recovery_spec.rb +34 -20
- data/spec/lib/pwn/setup_native_yubikey_spec.rb +66 -0
- data/spec/lib/pwn/setup_vault_yubikey_spec.rb +61 -0
- data/spec/lib/pwn/setup_yubikey_spec.rb +40 -0
- data/spec/lib/pwn/www/login_yubikey_spec.rb +273 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/harness/cli_faults.rb +13 -9
- data/spec/support/harness/controller_spill.rb +26 -0
- data/spec/support/harness/controller_state.rb +54 -0
- data/spec/support/harness/evaluate.rb +12 -1
- data/spec/support/harness/experiments.rb +1 -1
- data/spec/support/harness/fake_provider.rb +22 -6
- data/spec/support/harness/fault_preload.rb +3 -1
- data/spec/support/harness/mission_console.rb +54 -0
- data/spec/support/harness/mission_curses_pty.rb +41 -0
- data/spec/support/harness/mission_dispatch.rb +30 -0
- data/spec/support/harness/mission_fixture_preload.rb +24 -0
- data/spec/support/harness/mission_job_lifetime.rb +25 -0
- data/spec/support/harness/mission_legacy.rb +25 -0
- data/spec/support/harness/mission_normal_exit.rb +34 -0
- data/spec/support/harness/mission_swarm.rb +23 -0
- data/spec/support/harness/mission_unsupported.rb +29 -0
- data/spec/support/harness/package_acceptance.rb +33 -5
- data/spec/support/harness/session_acceptance.rb +4 -4
- data/spec/support/harness/swarm_acceptance.rb +1 -1
- data/spec/support/harness/swarm_control.rb +44 -0
- data/spec/support/mission_namespace.rb +14 -0
- data/spec/support/mission_pipe_queue.rb +33 -0
- data/third_party/pwn_rdoc.jsonl +605 -19
- metadata +129 -16
- data/scripts/benchmark_policy.rb +0 -376
- data/scripts/build_gate.rb +0 -58
- data/spec/integration/build_gate_spec.rb +0 -73
|
@@ -12,7 +12,7 @@ with a **tool-calling AI agent** on top that can run the same methods.
|
|
|
12
12
|
|
|
13
13
|
| Namespace | Count | What it is |
|
|
14
14
|
|---|---|---|
|
|
15
|
-
| `PWN::Plugins::*` | **
|
|
15
|
+
| `PWN::Plugins::*` | **108** | Wrappers for external and native tooling (Burp, Nmap, Metasploit, Shodan, browsers, serial, YubiKey, ...) |
|
|
16
16
|
| `PWN::SAST::*` | **48** | Static-analysis rules across C/Java/Go/Python/Ruby/Scala/PHP/TS |
|
|
17
17
|
| `PWN::AWS::*` | **90** | One module per AWS service for cloud enumeration |
|
|
18
18
|
| `PWN::WWW::*` | **22** | Site-specific browser automations (HackerOne, BugCrowd, GitHub, Google, LinkedIn, ...) |
|
|
@@ -20,7 +20,7 @@ with a **tool-calling AI agent** on top that can run the same methods.
|
|
|
20
20
|
| `PWN::FFI::*` | **11** | Native bindings (including DSPNative, Capstone and Keystone): Volk · Liquid · FFTW · RTLSdr · HackRF · AdalmPluto · SoapySDR · Stdio |
|
|
21
21
|
| `PWN::AI::*` | **6** engines | OpenAI, Anthropic, Grok (OAuth device-flow), Gemini, Ollama, Open WebUI |
|
|
22
22
|
| `bin/` (including `pwn-ai` and `pwn-capd`) | **56** | Headless CLI executables for CI/CD |
|
|
23
|
-
| Agent toolsets | **16** · **
|
|
23
|
+
| Agent toolsets | **16** · **152 tools** | terminal · pwn · memory · skills · sessions · learning · metrics · policy · extrospection · cron · swarm · reward · curriculum · http · mcp · manifest |
|
|
24
24
|
|
|
25
25
|
## Three ways to use it
|
|
26
26
|
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# YubiKey-backed vaults and authentication
|
|
2
|
+
|
|
3
|
+
See [YubiKey device operations](YubiKey.md) for native HID/PC/SC operations,
|
|
4
|
+
provisioning safeguards and the firmware boundary. No `ykman` process is used.
|
|
5
|
+
|
|
6
|
+
## Encryption model
|
|
7
|
+
|
|
8
|
+
This is **hardware-derived key encryption**, not bulk encryption inside the
|
|
9
|
+
YubiKey. An already provisioned OTP HMAC-SHA1 slot answers a fresh random
|
|
10
|
+
32-byte challenge. Ruby derives a 32-byte encryption key using HKDF-SHA256 with
|
|
11
|
+
a fresh 16-byte salt and a domain-specific context, then uses AES-256-GCM with
|
|
12
|
+
a fresh nonce and a full 16-byte tag. The HMAC response and derived key exist
|
|
13
|
+
transiently in the Ruby process; the slot secret is not exported. Ruby does not
|
|
14
|
+
promise zeroization of copied strings.
|
|
15
|
+
|
|
16
|
+
The versioned `PWN-YUBIKEY-VAULT:1` envelope authenticates its metadata as AAD.
|
|
17
|
+
The public challenge, salt, slot and optional serial are stored with ciphertext,
|
|
18
|
+
not in a secret sidecar. Executable paths and timeout overrides are supplied
|
|
19
|
+
by the caller, never loaded from ciphertext. PINs, OTP codes and serial numbers
|
|
20
|
+
are not encryption keys. HMAC-SHA1 is used as the device PRF, not as an
|
|
21
|
+
unauthenticated document hash; it provides at most the slot/response security,
|
|
22
|
+
not 256 bits of entropy merely because AES-256 is used.
|
|
23
|
+
|
|
24
|
+
Existing Base64 AES-256-CBC files and software loot remain readable. New
|
|
25
|
+
hardware protection is opt-in; no existing configuration is migrated merely by
|
|
26
|
+
loading PWN. A hardware envelope never falls back to a software master key,
|
|
27
|
+
passphrase or unauthenticated plaintext when a device is missing or a tag fails.
|
|
28
|
+
Do not combine a software key/IV or passphrase/keyring with hardware selection.
|
|
29
|
+
|
|
30
|
+
## Use an existing HMAC slot
|
|
31
|
+
|
|
32
|
+
Use a key model supporting OTP HMAC challenge-response. FIDO-only Security Keys
|
|
33
|
+
do not support this vault backend. Set up the slot explicitly using the device
|
|
34
|
+
management interface; prefer its physical-touch policy. PWN never provisions,
|
|
35
|
+
replaces, unlocks by guessing, or resets a slot in order to open a vault.
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
# The named file must already contain the plaintext you intend to encrypt.
|
|
39
|
+
PWN::Plugins::Vault.create(file: '/path/to/private.yaml', yubikey: { slot: 2 })
|
|
40
|
+
|
|
41
|
+
# With multiple devices, explicitly select the intended device serial.
|
|
42
|
+
# Serial is a placeholder; replace locally, never paste secrets into a transcript.
|
|
43
|
+
selector = { slot: 2, serial: '12345678' }
|
|
44
|
+
PWN::Plugins::Vault.encrypt(file: '/path/to/another.yaml', yubikey: selector)
|
|
45
|
+
|
|
46
|
+
# Read-only: decrypted data exists in memory, not an intermediate file.
|
|
47
|
+
config = PWN::Plugins::Vault.dump(file: '/path/to/private.yaml'); nil
|
|
48
|
+
|
|
49
|
+
# Mutate YAML in memory and atomically publish ciphertext, preserving the backend.
|
|
50
|
+
PWN::Plugins::Vault.update(file: '/path/to/private.yaml') do |document|
|
|
51
|
+
document[:setting] = 'replacement'
|
|
52
|
+
end
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`yubikey` is a Hash accepting `slot` (integer 1 or 2; default 2), optional
|
|
56
|
+
exact decimal `serial`, optional `reader` or `device_path`, and bounded
|
|
57
|
+
`timeout` seconds. An executable path such as `ykman` is rejected. The
|
|
58
|
+
envelope stores slot and serial only; it never stores a backend path.
|
|
59
|
+
`dump`, `decrypt`, `open_credentials` and hardware loot retrieval otherwise use
|
|
60
|
+
the slot/serial stored in their envelope. Selecting another serial permits an
|
|
61
|
+
explicitly provisioned recovery key with the same slot secret; the authentication
|
|
62
|
+
tag still has to verify. A different slot requires explicit rewrapping.
|
|
63
|
+
|
|
64
|
+
`encrypt_data` / `decrypt_data` are in-memory String APIs, including arbitrary
|
|
65
|
+
binary data and empty plaintext. `seal_credentials` / `open_credentials` work
|
|
66
|
+
on JSON-compatible credential values. Neither API opens the live configuration
|
|
67
|
+
or writes keys. `file_encrypted?` / `hardware_encrypted?` inspect format only;
|
|
68
|
+
they do not prove the device is present or that a ciphertext authenticates.
|
|
69
|
+
|
|
70
|
+
`decrypt(file:)` explicitly replaces ciphertext with plaintext. Use `dump`
|
|
71
|
+
instead when plaintext-on-disk is unnecessary. `edit` explicitly gives a private
|
|
72
|
+
0600 temporary copy to the chosen editor under `~/.pwn/workspaces/runtime`, then
|
|
73
|
+
removes its private working directory. The original stays encrypted until a
|
|
74
|
+
successful re-encryption and atomic replacement. Editors are trusted programs:
|
|
75
|
+
their external backups, OS swap, crash dumps and an abruptly killed process are
|
|
76
|
+
not a secure-erasure guarantee. The curses `/vault edit` editor works in memory
|
|
77
|
+
and writes only ciphertext. Built-in file writers share its parent-directory
|
|
78
|
+
advisory lock across the final baseline check and atomic rename. A stale edit
|
|
79
|
+
raises rather than overwriting a newer publication. This is not a filesystem
|
|
80
|
+
compare-and-swap guarantee against external writers that ignore the lock.
|
|
81
|
+
|
|
82
|
+
## Conversion and recovery
|
|
83
|
+
|
|
84
|
+
Before converting a legacy vault, retain its verified encrypted backup and
|
|
85
|
+
legacy decryptor somewhere secure. Conversion is explicit:
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
PWN::Plugins::Vault.refresh_encryption_secrets(
|
|
89
|
+
file: '/path/to/legacy.yaml',
|
|
90
|
+
key: legacy_key, iv: legacy_iv,
|
|
91
|
+
new_yubikey: { slot: 2 }
|
|
92
|
+
)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
No temporary plaintext is published during conversion. On an existing hardware
|
|
96
|
+
vault, `refresh_encryption_secrets(file:)` rewraps with fresh challenge/salt/nonce;
|
|
97
|
+
it does **not** change the device secret. Supply `new_yubikey:` to move to another
|
|
98
|
+
already provisioned slot/device while the old one is available. An explicit
|
|
99
|
+
`new_yubikey:` must be a valid selector Hash; values such as `false` are rejected
|
|
100
|
+
before opening the source vault, not treated as a request for software rotation.
|
|
101
|
+
Hardware access or encryption failure leaves the original ciphertext intact. Old software
|
|
102
|
+
sidecars and backups are not silently deleted; retire them deliberately after
|
|
103
|
+
verifying recovery.
|
|
104
|
+
|
|
105
|
+
Losing or reprogramming the only usable slot loses access. A ciphertext backup
|
|
106
|
+
alone is not an independent recovery key. Establish and test an appropriate
|
|
107
|
+
recovery device/secret before relying on hardware-only storage. Removing a
|
|
108
|
+
YubiKey does not erase an already unlocked `PWN::Env` or revoke remote tokens;
|
|
109
|
+
the application retains its in-memory configuration until exit/refresh.
|
|
110
|
+
|
|
111
|
+
## Integration coverage
|
|
112
|
+
|
|
113
|
+
| Entry point | Hardware behavior |
|
|
114
|
+
|---|---|
|
|
115
|
+
| `Vault.create/encrypt/decrypt/dump/edit/refresh_encryption_secrets` | Explicit creation/conversion, automatic envelope detection on read, backend-preserving edits |
|
|
116
|
+
| `Vault.seal_credentials/open_credentials` | Authenticated in-memory hardware envelopes alongside existing passphrase/keyring formats |
|
|
117
|
+
| `Vault.store/fetch/offer/ingest/expand/redact` | Optional hardware-protected engagement records; metadata-only `query` does not touch hardware |
|
|
118
|
+
| `BasicAuth.encode(host:)` | Resolves matching protected loot through Vault, not a separate crypto implementation |
|
|
119
|
+
| `Redaction.capture` and `Recon` loot ingestion | Explicit hardware selector for new captures; locked-store failure never creates a software-key fallback |
|
|
120
|
+
| `Config.default_env/refresh_env` | Explicit hardware creation; hardware loading without a legacy decryptor sidecar |
|
|
121
|
+
| `Migrate.vault_drift/backfill_vault` | Read/merge through Vault, preserving hardware format and user settings |
|
|
122
|
+
| `pwn-vault`, `/vault edit`, `/model`, `/system-role`, mesh settings | Backend-aware encrypted persistence; no duplicate CBC-only write path |
|
|
123
|
+
| OpenAI, Anthropic, Grok and Google Workspace OAuth persistence | In-memory configuration merge, ciphertext-only atomic save; hardware unavailability reports persistence failure |
|
|
124
|
+
| `AuthenticationHelper.mfa` and supported WWW login methods | Explicit exact-account OATH code lookup, separate from ordinary manual MFA |
|
|
125
|
+
|
|
126
|
+
Hardware-protected loot reads may require a touch, including explicit expansion
|
|
127
|
+
and secret-value redaction. Do not enable it for unattended workflows expecting
|
|
128
|
+
unbounded automatic access. Background metadata discovery and help do not unlock
|
|
129
|
+
hardware. Existing unrelated records are not implicitly re-encrypted. Missing
|
|
130
|
+
loot stores are empty; an existing unreadable store, malformed JSON, or invalid
|
|
131
|
+
record/envelope shape raises `IOError` on reads and writes, including metadata
|
|
132
|
+
queries. PWN does not infer a software backend from corrupt records, generate a
|
|
133
|
+
replacement master key, or overwrite the damaged store. Restore a verified backup
|
|
134
|
+
before retrying.
|
|
135
|
+
|
|
136
|
+
## Explicit OATH authentication
|
|
137
|
+
|
|
138
|
+
Select an exact account and authorize its effects explicitly:
|
|
139
|
+
|
|
140
|
+
```ruby
|
|
141
|
+
code = PWN::Plugins::AuthenticationHelper.mfa(
|
|
142
|
+
yubikey: { account: 'Example:alice', serial: '12345678', confirm: true }
|
|
143
|
+
); nil
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
The same `yubikey:` Hash is accepted by GitHub, Synack, Twitter, BugCrowd,
|
|
147
|
+
CoinbasePro and AppCobaltIO login methods. Lookup occurs at the authenticator
|
|
148
|
+
form, not during option validation. Missing/nonliteral consent is rejected before
|
|
149
|
+
password prompts or navigation. Device errors do not fall back to manual MFA;
|
|
150
|
+
explicit manual tokens cannot be combined with the hardware selector. PayPal's
|
|
151
|
+
current SMS-only adapter rejects OATH even with consent, and GitHub's SMS-only
|
|
152
|
+
challenge does not accept an authenticator code.
|
|
153
|
+
|
|
154
|
+
For `pwn_web_cache_deception`, add `--yubikey-account='Example:alice'`, optionally
|
|
155
|
+
`--yubikey-serial=12345678`, and the required `--yubikey-confirm` to the normal
|
|
156
|
+
arguments for a compatible login module. The flag authorizes native OATH
|
|
157
|
+
authentication and HOTP counter advancement. It does not authorize deleting or
|
|
158
|
+
repairing a corrupted credential. It is required for TOTP too; PWN never
|
|
159
|
+
silently supplies consent.
|
|
160
|
+
Confirmation/serial flags without an account are rejected before login.
|
|
161
|
+
|
|
162
|
+
## Scope boundaries
|
|
163
|
+
|
|
164
|
+
YubiKey FIDO management is not a WebAuthn relying-party implementation. Website
|
|
165
|
+
passkey login still requires the browser's genuine security-key ceremony and
|
|
166
|
+
site enrollment; a generated OATH code must never be submitted to an SMS-only
|
|
167
|
+
challenge. PIV/OpenPGP key management does not export non-exportable keys or
|
|
168
|
+
magically replace TLS, SSH-agent or GPG-provider integrations.
|
|
169
|
+
|
|
170
|
+
Radio protocol keys, packet AES-CCM, TLS inspection certificates, OAuth PKCE,
|
|
171
|
+
artifact hashes, cloud KMS/HSM API clients and Jenkins private-key uploads are
|
|
172
|
+
not rewritten to use hardware-derived bytes. Their stored credentials can be
|
|
173
|
+
protected through Vault where appropriate.
|
|
174
|
+
|
|
175
|
+
Hardware-backed loot does not encrypt Recon's raw evidence/asset files, generic
|
|
176
|
+
tool-result artifacts, exports, or the filesystem as a whole. Those retain their
|
|
177
|
+
existing evidence-storage behavior and need separate access/at-rest protection.
|
|
178
|
+
`recon_run` advertises the same nonsecret hardware selector as `loot_query` for
|
|
179
|
+
harvested loot; metadata-only Vault queries do not unlock a device, but Dispatch's
|
|
180
|
+
separate output-redaction step can still require access to protected secrets.
|
|
181
|
+
|
|
182
|
+
Verification uses synthetic native connections and HMAC responses. Tests
|
|
183
|
+
exercise real Ruby encryption, authentication failures, selector validation
|
|
184
|
+
and persistence entry points. They are not evidence of a physical YubiKey,
|
|
185
|
+
live website authentication or every firmware variant.
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# YubiKey device operations
|
|
2
|
+
|
|
3
|
+
`PWN::Plugins::YubiKey` implements YubiKey application protocols in Ruby. It
|
|
4
|
+
talks to the device through HIDAPI and PC/SC (`::FFI` bindings to those host
|
|
5
|
+
libraries). It does not start `ykman`, another device CLI, a Python helper, or
|
|
6
|
+
any subprocess. It is not a WebAuthn relying party.
|
|
7
|
+
|
|
8
|
+
Hardware capability and firmware still decide which operations succeed. Fixture
|
|
9
|
+
tests are not physical-key interoperability, and this page does not claim every
|
|
10
|
+
model or firmware revision.
|
|
11
|
+
|
|
12
|
+
For encrypted configuration, credential storage, conversion and recovery, see
|
|
13
|
+
[YubiKey-backed vaults and authentication](YubiKey-Vaults.md).
|
|
14
|
+
|
|
15
|
+
## Dependency and discovery
|
|
16
|
+
|
|
17
|
+
`required_bins` is empty. Core setup does not install hardware packages. The
|
|
18
|
+
`hardware` profile maps optional host libraries (`hidapi`, `pcsc`), not an
|
|
19
|
+
executable. Loading the module does not open a device. `available?` only probes
|
|
20
|
+
those libraries. A missing library, a missing device, a permission failure and
|
|
21
|
+
an unsupported application are different conditions. Preflight reports
|
|
22
|
+
`FIDO native transport` and `PC/SC native transport` without discovering
|
|
23
|
+
hardware. See [Plugin Degradation](Plugin-Degradation.md#pwn-plugins-yubikey).
|
|
24
|
+
|
|
25
|
+
```ruby
|
|
26
|
+
require 'pwn'
|
|
27
|
+
yk = PWN::Plugins::YubiKey
|
|
28
|
+
yk.required_bins # => []
|
|
29
|
+
yk.available?(backend: 'hid') # library probe; no device open
|
|
30
|
+
yk.devices # explicit listing; may be []
|
|
31
|
+
yk.info(serial: '12345678') # example serial; replace locally
|
|
32
|
+
yk.otp(args: ['info'], serial: '12345678')
|
|
33
|
+
yk.help # public methods and option descriptions
|
|
34
|
+
yk.cli_help # local native help metadata, not a CLI process
|
|
35
|
+
yk.cli_help(path: %w[piv keys generate])
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
There is no `ykman:` path option. Executable paths, stdin, log files and inline
|
|
39
|
+
credential argv are rejected. Serial values must be decimal Strings; they are
|
|
40
|
+
not trimmed or coerced. Omit the serial only when selection is unambiguous.
|
|
41
|
+
PWN never chooses the first of several devices. `reader:` and `device_path:`
|
|
42
|
+
are mutually exclusive with each other and with `serial:` when more than one
|
|
43
|
+
is set. A caller-owned `connection:` stays open; PWN closes only handles it
|
|
44
|
+
opened.
|
|
45
|
+
|
|
46
|
+
## Native application coverage
|
|
47
|
+
|
|
48
|
+
Family methods take `args:` as an argv Array **after the family name**. With
|
|
49
|
+
no `args`, they return that family's local help metadata. `command(args:)`
|
|
50
|
+
takes the complete nonsecret argv, including the family name, and dispatches
|
|
51
|
+
to the matching Ruby application. It returns the application result; it does
|
|
52
|
+
not print or log it.
|
|
53
|
+
|
|
54
|
+
| Method | Application | Covered operations |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| `config` | management | USB/NFC application enablement, mode, lock code, timeouts, reset |
|
|
57
|
+
| `otp` | OTP | Slot inventory, Yubico OTP, static password, HOTP, HMAC challenge-response, settings, NDEF, swap, delete |
|
|
58
|
+
| `oath` | OATH | Account list/add/URI/import/rename/delete/code, access password, caller-owned cache, reset |
|
|
59
|
+
| `fido` | FIDO | PIN changes/verification, minimum PIN length, resident credential list/delete, fingerprints, UV/attestation policy, reset |
|
|
60
|
+
| `piv` | PIV | PIN/PUK/management key, key generation/import/export/move/delete/attestation, certificates, CSR and object management, reset |
|
|
61
|
+
| `openpgp` | OpenPGP | PIN/admin/reset code and retry policy, key import/attestation/touch policy, certificates, reset |
|
|
62
|
+
| `hsmauth` | HSM Auth | Asymmetric/symmetric/derived credentials, credential passwords, management protection, reset |
|
|
63
|
+
| `security_domain` | Security Domain | SCP key information, generation/import/export/deletion/allowlists and reset |
|
|
64
|
+
| `apdu` | smartcard | Explicit APDUs. Mutations require `confirm: true` |
|
|
65
|
+
|
|
66
|
+
Unknown command grammar is rejected. Do not pass a shell string. Use separate
|
|
67
|
+
argv elements: `args: ['keys', 'info', '9a']`, not `args: 'keys info 9a'`.
|
|
68
|
+
Short aliases and `--option=value` are rejected. `--` is available before a
|
|
69
|
+
positional identifier that begins with a dash.
|
|
70
|
+
|
|
71
|
+
### Confirmation, secrets and deadlines
|
|
72
|
+
|
|
73
|
+
Existing-slot HMAC calculation is the vault unlock path. Omitted `confirm` is
|
|
74
|
+
allowed. If `confirm` is present it must be literal `true`; `false`, `nil` and
|
|
75
|
+
`'true'` are rejected before any open.
|
|
76
|
+
|
|
77
|
+
Mutations, OATH calculation, provisioning and raw APDUs require literal
|
|
78
|
+
`confirm: true` before the device is opened. Confirmation does not guess
|
|
79
|
+
factory PINs, retry a blocked application, or delete a credential. Native OATH
|
|
80
|
+
does not delete or repair a corrupted credential. HOTP still advances its
|
|
81
|
+
counter. A password-protected OATH account needs an in-memory `password:` or
|
|
82
|
+
`access_key:`, or a caller `secret_provider`.
|
|
83
|
+
|
|
84
|
+
PINs, PUKs, management keys, access codes and OATH passwords stay in memory or
|
|
85
|
+
come from that provider. They are not argv, exception text, or logs. For a
|
|
86
|
+
private operator terminal, outside an agent request:
|
|
87
|
+
|
|
88
|
+
```ruby
|
|
89
|
+
yk.interact(
|
|
90
|
+
args: %w[fido access change-pin], serial: '12345678',
|
|
91
|
+
confirm: true, operator: true, timeout: 90
|
|
92
|
+
)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`interact` prompts on the controlling console, or on an explicitly supplied
|
|
96
|
+
readable and writable `terminal:` IO, then runs one native command. It returns
|
|
97
|
+
only `:completed`. It does not start a process, retain a transcript, or close
|
|
98
|
+
caller-owned IO. Run it outside curses and recorded tool sessions. Ruby does
|
|
99
|
+
not guarantee string zeroization.
|
|
100
|
+
|
|
101
|
+
`timeout:` is one finite positive budget in seconds, default **30**. It covers
|
|
102
|
+
open, secure-channel setup, authentication and commands. Remaining time is
|
|
103
|
+
what later exchanges receive; each step does not get a fresh 30 seconds.
|
|
104
|
+
`SCardCancel` does not universally interrupt `SCardTransmit`, and killing a
|
|
105
|
+
Ruby thread does not cancel a native driver call. After a timeout or
|
|
106
|
+
interruption, inspect device state before retrying a mutation.
|
|
107
|
+
|
|
108
|
+
Missing libraries, command failure, timeout, output limits and malformed
|
|
109
|
+
responses raise `DependencyError`, `CommandError`, `TimeoutError`,
|
|
110
|
+
`OutputLimitError` or `ResponseError`. These inherit from `YubiKey::Error`.
|
|
111
|
+
Missing consent raises `ConfirmationRequired`. Invalid caller values raise
|
|
112
|
+
`ArgumentError`. Errors do not include request bytes.
|
|
113
|
+
|
|
114
|
+
### Secure channel
|
|
115
|
+
|
|
116
|
+
`secure_channel:` is an explicit Hash, not a file of inline CLI keys. It
|
|
117
|
+
requires `scp:` (`:scp03`, `:scp11a`, `:scp11b` or `:scp11c`) and integer
|
|
118
|
+
`kvn:`. SCP03 also requires 16-byte in-memory `key_enc` and `key_mac`. A
|
|
119
|
+
failed secure-channel handshake does not fall back to plaintext. The owned
|
|
120
|
+
handle is still closed.
|
|
121
|
+
|
|
122
|
+
## Existing-slot HMAC challenge-response
|
|
123
|
+
|
|
124
|
+
```ruby
|
|
125
|
+
require 'securerandom'
|
|
126
|
+
challenge = SecureRandom.random_bytes(32) # Public challenge, not a provisioning key.
|
|
127
|
+
response = PWN::Plugins::YubiKey.challenge_response(
|
|
128
|
+
challenge: challenge,
|
|
129
|
+
slot: 2,
|
|
130
|
+
serial: '12345678',
|
|
131
|
+
timeout: 30
|
|
132
|
+
); nil # Suppress sensitive return-value echo in an interactive console.
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`challenge:` is a raw Ruby String of **1–64 bytes**, not pre-encoded hex.
|
|
136
|
+
`slot:` is integer **1 or 2**, default **2**. The return value is exactly
|
|
137
|
+
**20 raw bytes**, encoding `ASCII-8BIT`. A touch-enabled slot requires a
|
|
138
|
+
physical touch before timeout. Missing or incompatible slots fail. This method
|
|
139
|
+
never programs, resets or repairs a slot. FIDO-only Security Key models cannot
|
|
140
|
+
provide this OTP HMAC operation.
|
|
141
|
+
|
|
142
|
+
The challenge is not placed on a child argv, because no child is started. Do
|
|
143
|
+
not use a password as the challenge. The HMAC response is sensitive key
|
|
144
|
+
material in the Ruby process.
|
|
145
|
+
|
|
146
|
+
## Explicit HMAC provisioning
|
|
147
|
+
|
|
148
|
+
Provisioning is separate from authentication and vault unlock. It **overwrites
|
|
149
|
+
the chosen slot**. The existing HMAC secret cannot be read back. Keep another
|
|
150
|
+
authentication method, and test recovery before discarding the new key.
|
|
151
|
+
|
|
152
|
+
```ruby
|
|
153
|
+
require 'securerandom'
|
|
154
|
+
secret_key = SecureRandom.random_bytes(20); nil
|
|
155
|
+
PWN::Plugins::YubiKey.provision_challenge_response(
|
|
156
|
+
key: secret_key,
|
|
157
|
+
serial: '12345678',
|
|
158
|
+
slot: 2,
|
|
159
|
+
confirm: true,
|
|
160
|
+
timeout: 30
|
|
161
|
+
) # => :verified only after a fresh challenge matches the supplied key
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
`confirm: true` is required before open. An explicit serial, reader,
|
|
165
|
+
device path or caller-owned connection is required. `touch:` defaults to
|
|
166
|
+
`true`. Optional access codes are six raw bytes, supplied in memory, not at a
|
|
167
|
+
CLI prompt. The method checks a fresh challenge with Ruby OpenSSL HMAC-SHA1
|
|
168
|
+
and returns `:verified` only when that check passes. Touch the device when the
|
|
169
|
+
slot requires it. If programming succeeds and readback fails, the slot may
|
|
170
|
+
already have changed: inspect it before retrying. Do not assume rollback.
|
|
171
|
+
|
|
172
|
+
## Exact OATH retrieval
|
|
173
|
+
|
|
174
|
+
```ruby
|
|
175
|
+
code = PWN::Plugins::YubiKey.oath_code(
|
|
176
|
+
account: 'Example:alice', # Exact identifier, not a substring.
|
|
177
|
+
serial: '12345678',
|
|
178
|
+
confirm: true,
|
|
179
|
+
timeout: 30
|
|
180
|
+
); nil
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
The result is **6–8 decimal digits**, preserving leading zeros. The account
|
|
184
|
+
must be an exact control-free String of 1 to 64 bytes. Steam alphanumeric
|
|
185
|
+
codes are outside this method. `confirm: true` is required before open, including
|
|
186
|
+
for TOTP, because HOTP advances its counter and a protected account may
|
|
187
|
+
authenticate. Consent does not authorize deleting a corrupted credential.
|
|
188
|
+
Device errors do not fall back to a manual token.
|
|
189
|
+
|
|
190
|
+
## Authentication and interoperability limits
|
|
191
|
+
|
|
192
|
+
FIDO PIN, resident-credential and fingerprint management is **not website
|
|
193
|
+
login**. U2F/FIDO2/WebAuthn enrollment and assertions belong to the browser and
|
|
194
|
+
relying party. This module does not fabricate assertions. Submit an OATH code
|
|
195
|
+
only to a matching authenticator-code challenge, never an SMS-only or passkey
|
|
196
|
+
challenge. PayPal's SMS adapter rejects hardware OATH before login.
|
|
197
|
+
|
|
198
|
+
PIV and OpenPGP management do not supply a TLS client, SSH agent or GPG
|
|
199
|
+
middleware, and do not export non-exportable private keys. YubiHSM Auth
|
|
200
|
+
credentials are not a YubiHSM. Device and firmware errors stay errors. They do
|
|
201
|
+
not trigger reset, provisioning, a software-secret fallback, or repeated PIN
|
|
202
|
+
attempts.
|
|
203
|
+
|
|
204
|
+
## Offline verification
|
|
205
|
+
|
|
206
|
+
```text
|
|
207
|
+
bundle exec rspec spec/lib/pwn/plugins/yubikey_spec.rb spec/lib/pwn/plugins/yubikey_security_spec.rb spec/lib/pwn/plugins/yubikey_terminal_spec.rb
|
|
208
|
+
bundle exec rubocop lib/pwn/plugins/yubikey.rb spec/lib/pwn/plugins/yubikey_spec.rb spec/lib/pwn/plugins/yubikey_security_spec.rb spec/lib/pwn/plugins/yubikey_terminal_spec.rb
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Those specs use synthetic connections and credentials, including an independent
|
|
212
|
+
RFC 2202 HMAC-SHA1 vector. They do not open a physical key, log in to a website,
|
|
213
|
+
or prove every firmware variant. USB/NFC, touch, PIN protection and real
|
|
214
|
+
relying-party login remain separate opt-in checks.
|
|
215
|
+
|
|
216
|
+
- [RFC 2202 HMAC test vectors](https://www.rfc-editor.org/rfc/rfc2202)
|
|
217
|
+
- [GlobalPlatform Card Specification](https://globalplatform.org/specs-library/card-specification/)
|
|
218
|
+
- [Yubico OTP protocol notes](https://developers.yubico.com/OTP/)
|