Coverage for tests / data / __init__.py: 100.000%
261 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-07-06 21:34 +0200
« prev ^ index » next coverage.py v7.13.1, created at 2026-07-06 21:34 +0200
1# SPDX-FileCopyrightText: 2026 Marco Ricci <software@the13thletter.info>
2#
3# SPDX-License-Identifier: Zlib
5"""Testing data for `derivepassphrase`.
7This is all the standalone, non-test-system-specific data set aside
8specifically to test `derivepassphrase`; this includes types, `vault`
9test configurations, test SSH keys and the like.
11This module only contains data, and some "mostly trivial" code such as
12accessors or suitability checkers; all code more complicated than that
13is in the `tests.data.callables` module (if independent of, and sensible
14to call outside, the testing environment) or the `tests.machinery`
15module (otherwise). All data that specifically relates to the testing
16system itself is also in the `tests.machinery` module, not here.
18"""
20from __future__ import annotations
22import base64
23import copy
24import ctypes
25import enum
26import errno
27import os
28import socket
29from typing import TYPE_CHECKING, cast
31from typing_extensions import NamedTuple, assert_never
33from derivepassphrase import _types, ssh_agent, vault
34from derivepassphrase.ssh_agent import socketprovider
36__all__ = ()
38if TYPE_CHECKING:
39 from collections.abc import Mapping
40 from typing import NoReturn
42 import pytest
43 from typing_extensions import Any
46# Actions
47# =======
50class ListKeysAction(str, enum.Enum):
51 """Test fixture settings for [`ssh_agent.SSHAgentClient.list_keys`][].
53 Attributes:
54 EMPTY: Return an empty key list.
55 FAIL: Raise an [`ssh_agent.SSHAgentFailedError`][].
56 FAIL_RUNTIME: Raise an [`ssh_agent.TrailingDataError`][].
58 """
60 EMPTY = enum.auto()
61 """"""
62 FAIL = enum.auto()
63 """"""
64 FAIL_RUNTIME = enum.auto()
65 """"""
67 def __call__(self, *_args: Any, **_kwargs: Any) -> Any:
68 """Execute the respective action."""
69 # TODO(the-13th-letter): Rewrite using structural pattern
70 # matching.
71 # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9
72 if self == self.EMPTY: 1b
73 return [] 1b
74 if self == self.FAIL: 1b
75 raise ssh_agent.SSHAgentFailedError(_types.SSH_AGENT.FAILURE, b"") 1b
76 if self == self.FAIL_RUNTIME: 1b
77 raise ssh_agent.TrailingDataError() 1b
78 raise AssertionError()
81class SignAction(str, enum.Enum):
82 """Test fixture settings for [`ssh_agent.SSHAgentClient.sign`][].
84 Attributes:
85 FAIL: Raise an [`ssh_agent.SSHAgentFailedError`][].
86 FAIL_RUNTIME: Raise an [`ssh_agent.TrailingDataError`][].
88 """
90 FAIL = enum.auto()
91 """"""
92 FAIL_RUNTIME = enum.auto()
93 """"""
95 def __call__(self, *_args: Any, **_kwargs: Any) -> Any:
96 """Execute the respective action."""
97 # TODO(the-13th-letter): Rewrite using structural pattern
98 # matching.
99 # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9
100 if self == self.FAIL: 1b
101 raise ssh_agent.SSHAgentFailedError(_types.SSH_AGENT.FAILURE, b"") 1b
102 if self == self.FAIL_RUNTIME: 1b
103 raise ssh_agent.TrailingDataError() 1b
104 raise AssertionError()
107class SocketAddressAction(str, enum.Enum):
108 """Test fixture settings for the SSH agent socket address.
110 Attributes:
111 MANGLE_ADDRESS:
112 Mangle the socket address.
114 For UNIX domain sockets, mangle the `SSH_AUTH_SOCK`
115 environment variable.
117 For Windows named pipes, skip the test. (Addresses are
118 fixed, so cannot be mangled.)
119 UNSET_ADDRESS:
120 Unset the socket address.
122 For UNIX domain sockets, unset the `SSH_AUTH_SOCK`
123 environment variable.
125 For Windows named pipes, skip the test. (Adresses are
126 fixed, so cannot be unset.)
128 """
130 MANGLE_ADDRESS = enum.auto()
131 """"""
132 UNSET_ADDRESS = enum.auto()
133 """"""
135 def __call__(
136 self, monkeypatch: pytest.MonkeyPatch, /, *_args: Any, **_kwargs: Any
137 ) -> None:
138 """Execute the respective action."""
139 # TODO(the-13th-letter): Rewrite using structural pattern
140 # matching.
141 # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9
142 if self == self.MANGLE_ADDRESS: 1b
144 def mangled_address( 1b
145 *_args: Any, **_kwargs: Any 1b
146 ) -> NoReturn: # pragma: no cover [failsafe] 1b
147 raise OSError(errno.ENOENT, os.strerror(errno.ENOENT))
149 monkeypatch.setattr( 1b
150 socketprovider.WindowsNamedPipeHandle,
151 "for_pageant",
152 mangled_address,
153 )
154 monkeypatch.setattr( 1b
155 socketprovider.WindowsNamedPipeHandle,
156 "for_openssh",
157 mangled_address,
158 )
159 monkeypatch.setenv( 1b
160 "SSH_AUTH_SOCK",
161 os.environ["SSH_AUTH_SOCK"] + "~"
162 if "SSH_AUTH_SOCK" in os.environ
163 else socketprovider.PIPE_PREFIX
164 if os.name == "nt"
165 else "/",
166 )
167 elif self == self.UNSET_ADDRESS: 1b
169 def no_address( 1b
170 *_args: Any, **_kwargs: Any 1b
171 ) -> NoReturn: # pragma: no cover [failsafe] 1b
172 raise KeyError("SSH_AUTH_SOCK") # noqa: EM101
174 monkeypatch.setattr( 1b
175 socketprovider.WindowsNamedPipeHandle,
176 "for_pageant",
177 no_address,
178 )
179 monkeypatch.setattr( 1b
180 socketprovider.WindowsNamedPipeHandle,
181 "for_openssh",
182 no_address,
183 )
184 monkeypatch.delenv("SSH_AUTH_SOCK", raising=False) 1b
185 else:
186 raise AssertionError()
189class SystemSupportAction(str, enum.Enum):
190 """Test fixture settings for [`ssh_agent.SSHAgentClient`][] system support.
192 Attributes:
193 UNSET_AF_UNIX_AND_ENSURE_USE:
194 Ensure lack of support for UNIX domain sockets, and that the
195 agent will use this socket provider.
196 UNSET_NATIVE_AND_ENSURE_USE:
197 Ensure both `UNSET_AF_UNIX` and `UNSET_WINDLL`, and that the
198 agent will use the native socket provider.
199 UNSET_PROVIDER_LIST:
200 Ensure an empty list of SSH agent socket providers.
201 UNSET_WINDLL_AND_ENSURE_USE:
202 Ensure lack of support for Windows named pipes, and that the
203 agent will use this socket provider.
205 """
207 UNSET_AF_UNIX_AND_ENSURE_USE = enum.auto()
208 """"""
209 UNSET_NATIVE_AND_ENSURE_USE = enum.auto()
210 """"""
211 UNSET_PROVIDER_LIST = enum.auto()
212 """"""
213 UNSET_WINDLL_AND_ENSURE_USE = enum.auto()
214 """"""
216 def __call__(
217 self, monkeypatch: pytest.MonkeyPatch, /, *_args: Any, **_kwargs: Any
218 ) -> None:
219 """Execute the respective action.
221 Args:
222 monkeypatch: The current monkeypatch context.
224 """
225 # TODO(the-13th-letter): Rewrite using structural pattern
226 # matching.
227 # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9
228 if self == self.UNSET_PROVIDER_LIST: 1cbd
229 monkeypatch.setattr( 1b
230 ssh_agent.SSHAgentClient, "SOCKET_PROVIDERS", []
231 )
232 elif self == self.UNSET_NATIVE_AND_ENSURE_USE: 1cbd
233 monkeypatch.setattr( 1b
234 ssh_agent.SSHAgentClient,
235 "SOCKET_PROVIDERS",
236 [_types.BuiltinSSHAgentSocketProvider.NATIVE],
237 )
238 monkeypatch.delattr(socket, "AF_UNIX", raising=False) 1b
239 monkeypatch.delattr(ctypes, "WinDLL", raising=False) 1b
240 monkeypatch.delattr(ctypes, "windll", raising=False) 1b
241 elif self == self.UNSET_AF_UNIX_AND_ENSURE_USE: 1cbd
242 monkeypatch.setattr( 1cbd
243 ssh_agent.SSHAgentClient,
244 "SOCKET_PROVIDERS",
245 [_types.BuiltinSSHAgentSocketProvider.SSH_AUTH_SOCK_ON_POSIX],
246 )
247 monkeypatch.delattr(socket, "AF_UNIX", raising=False) 1cbd
248 elif self == self.UNSET_WINDLL_AND_ENSURE_USE: 1cbd
249 monkeypatch.setattr( 1cbd
250 ssh_agent.SSHAgentClient,
251 "SOCKET_PROVIDERS",
252 [_types.BuiltinSSHAgentSocketProvider.WINDOWS_NAMED_PIPE],
253 )
254 monkeypatch.delattr(ctypes, "WinDLL", raising=False) 1cbd
255 monkeypatch.delattr(ctypes, "windll", raising=False) 1cbd
256 else:
257 raise AssertionError()
260# Types
261# =====
263# SSH test keys and agent info
264# ----------------------------
267class SSHTestKeyDeterministicSignatureClass(str, enum.Enum):
268 """The class of a deterministic signature from an SSH test key.
270 Attributes:
271 SPEC:
272 A deterministic signature directly implied by the
273 specification of the signature algorithm.
274 RFC_6979:
275 A deterministic signature as specified by RFC 6979. Only
276 used with DSA and ECDSA keys (that aren't also EdDSA keys).
277 Pageant_068_080:
278 A deterministic signature as specified by Pageant 0.68.
279 Only used with DSA and ECDSA keys (that aren't also EdDSA
280 keys), and only used with Pageant from 0.68 up to and
281 including 0.80.
283 Usage of this signature class together with an ECDSA NIST
284 P-521 key [turned out to leak enough information per
285 signature to quickly compromise the entire private key
286 (CVE-2024-31497)][PUTTY_CVE_2024_31497], so newer Pageant
287 versions abandon this signature class in favor of RFC 6979.
289 [PUTTY_CVE_2024_31497]: https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/vuln-p521-bias.html
291 """
293 SPEC = enum.auto()
294 """"""
295 RFC_6979 = enum.auto()
296 """"""
297 Pageant_068_080 = enum.auto()
298 """"""
301class SSHTestKeyDeterministicSignature(NamedTuple):
302 """An SSH test key deterministic signature.
304 Attributes:
305 signature:
306 The binary signature of the [vault UUID][vault.Vault.UUID]
307 under this signature class.
308 derived_passphrase:
309 The equivalent master passphrase derived from this
310 signature.
311 signature_class:
312 The [signature
313 class][SSHTestKeyDeterministicSignatureClass].
315 """
317 signature: bytes
318 """"""
319 derived_passphrase: bytes
320 """"""
321 signature_class: SSHTestKeyDeterministicSignatureClass = (
322 SSHTestKeyDeterministicSignatureClass.SPEC
323 )
324 """"""
327class SSHTestKey(NamedTuple):
328 """An SSH test key.
330 Attributes:
331 public_key:
332 The SSH public key string, as used e.g. by OpenSSH's
333 `authorized_keys` file. Includes a comment.
334 public_key_data:
335 The SSH protocol wire format of the public key.
336 private_key:
337 A base64 encoded representation of the private key, in
338 OpenSSH's v1 private key format.
339 private_key_blob:
340 The SSH protocol wire format of the private key.
341 expected_signatures:
342 A mapping of deterministic signature classes to the
343 expected, deterministic signature (of that class) of the
344 vault UUID for this key, together with the respective
345 "equivalent master passphrase" derived from this signature.
347 """
349 public_key: bytes
350 """"""
351 public_key_data: bytes
352 """"""
353 private_key: bytes
354 """"""
355 private_key_blob: bytes
356 """"""
357 expected_signatures: Mapping[
358 SSHTestKeyDeterministicSignatureClass, SSHTestKeyDeterministicSignature
359 ]
360 """"""
362 def is_suitable(
363 self,
364 *,
365 client: ssh_agent.SSHAgentClient | None = None,
366 ) -> bool:
367 """Return if this key is suitable for use with vault.
369 Args:
370 client:
371 An optional SSH agent client to check for additional
372 deterministic key types. If not given, assume no such
373 types.
375 """
376 return vault.Vault.is_suitable_ssh_key( 1ai
377 self.public_key_data, client=client
378 )
381class KnownSSHAgentType(str, enum.Enum):
382 """Known SSH agent types.
384 Attributes:
385 UNKNOWN (str):
386 Not a known agent, or not known statically.
387 UNIXPageant (str):
388 The agent from Simon Tatham's PuTTY suite (on
389 UNIX/BSD/POSIX).
390 OpenSSHAgent (str):
391 The agent from OpenBSD's OpenSSH suite (on UNIX/BSD/POSIX).
392 Pageant (str):
393 The agent from Simon Tatham's PuTTY suite (on The Annoying
394 OS).
395 OpenSSHAgentOnWindows (str):
396 The agent from OpenBSD's OpenSSH suite (PowerShell/Windows
397 version, on The Annoying OS).
398 StubbedSSHAgent (str):
399 The stubbed, fake agent pseudo-socket defined in this test
400 suite.
402 """
404 UNKNOWN = "(unknown)"
405 """"""
406 UNIXPageant = "UNIXPageant"
407 """"""
408 OpenSSHAgent = "OpenSSHAgent"
409 """"""
410 Pageant = "Pageant"
411 """"""
412 OpenSSHAgentOnWindows = "OpenSSHAgentOnWindows"
413 """"""
414 StubbedSSHAgent = "StubbedSSHAgent"
415 """"""
418class KnownSSHAgentInstance(str, enum.Enum):
419 """Known SSH agent instances, as test cases/configurations.
421 Attributes:
422 pageant:
423 An instance of [`Pageant`][KnownSSHAgentType.Pageant].
424 openssh:
425 An instance of
426 [`OpenSSHAgent`][KnownSSHAgentType.OpenSSHAgent].
427 unix_pageant:
428 An instance of
429 [`UNIXPageant`][KnownSSHAgentType.UNIXPageant].
430 openssh_on_windows:
431 An instance of
432 [`OpenSSHAgentOnWindows`][KnownSSHAgentType.OpenSSHAgentOnWindows].
433 stub_agent_with_address:
434 An instance of
435 [`StubbedSSHAgent`][KnownSSHAgentType.StubbedSSHAgent] with
436 a specific "socket address".
437 stub_agent_with_address_and_deterministic_dsa:
438 An instance of
439 [`StubbedSSHAgent`][KnownSSHAgentType.StubbedSSHAgent] with
440 a specific "socket address" that also support deterministic
441 DSA signatures.
442 system_agent:
443 The system agent, of [unknown][KnownSSHAgentType.UNKNOWN]
444 type.
446 """
448 pageant = "pageant"
449 """"""
450 openssh = "openssh"
451 """"""
452 unix_pageant = "unix_pageant"
453 """"""
454 openssh_on_windows = "openssh_on_windows"
455 """"""
456 stub_agent_with_address = "stub_agent_with_address"
457 """"""
458 stub_agent_with_address_and_deterministic_dsa = (
459 "stub_agent_with_address_and_deterministic_dsa"
460 )
461 """"""
462 system_agent = "system_agent"
463 """"""
465 @property
466 def agent_type(self) -> KnownSSHAgentType:
467 """The agent type for this instance."""
468 # TODO(the-13th-letter): Rewrite using structural pattern
469 # matching.
470 # https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9
471 if self == KnownSSHAgentInstance.pageant:
472 return KnownSSHAgentType.Pageant
473 if self == KnownSSHAgentInstance.openssh:
474 return KnownSSHAgentType.OpenSSHAgent
475 if self == KnownSSHAgentInstance.unix_pageant:
476 return KnownSSHAgentType.UNIXPageant
477 if self == KnownSSHAgentInstance.openssh_on_windows:
478 return KnownSSHAgentType.OpenSSHAgentOnWindows
479 if self == KnownSSHAgentInstance.stub_agent_with_address:
480 return KnownSSHAgentType.StubbedSSHAgent
481 if (
482 self
483 == KnownSSHAgentInstance.stub_agent_with_address_and_deterministic_dsa
484 ):
485 return KnownSSHAgentType.StubbedSSHAgent
486 if self == KnownSSHAgentInstance.system_agent:
487 return KnownSSHAgentType.UNKNOWN
488 assert_never(self)
491class SpawnedSSHAgentInfo(NamedTuple):
492 """Info about a spawned SSH agent, as provided by some fixtures.
494 Differs from [`RunningSSHAgentInfo`][] in that this info object
495 already provides a functional client connected to the agent, but not
496 the address.
498 Attributes:
499 agent_type:
500 The agent's type.
501 client:
502 An SSH agent client connected to this agent.
503 isolated:
504 Whether this agent was spawned specifically for this test
505 suite, with attempts to isolate it from the user. If false,
506 then the user may be interacting with the agent externally,
507 meaning e.g. keys other than the test keys may be visible in
508 this agent.
510 """
512 agent_type: KnownSSHAgentType
513 """"""
514 client: ssh_agent.SSHAgentClient
515 """"""
516 isolated: bool
517 """"""
520class RunningSSHAgentInfo(NamedTuple):
521 """Info about a running SSH agent, as provided by some fixtures.
523 Differs from [`SpawnedSSHAgentInfo`][] in that this info object
524 provides only an address of the agent, not a functional client
525 already connected to it. The running SSH agent may or may not be
526 isolated.
528 Attributes:
529 socket:
530 A socket address to connect to the agent.
531 agent_type:
532 The agent's type.
534 """
536 socket: str | type[_types.SSHAgentSocket]
537 """"""
538 agent_type: KnownSSHAgentType
539 """"""
541 def require_external_address(self) -> str: # pragma: no cover
542 if not isinstance(self.socket, str):
543 import pytest # noqa: PLC0415
545 pytest.skip(
546 reason="This test requires a real, externally resolvable "
547 "address for the SSH agent socket."
548 )
549 return self.socket
552class AgentProtocolRequest(NamedTuple):
553 """A request for the SSH agent protocol.
555 Attributes:
556 code:
557 The expected request code.
558 payload:
559 The expected payload. Optional.
561 """
563 code: _types.SSH_AGENTC | int
564 """"""
565 payload: bytes
566 """"""
569class AgentProtocolResponse(NamedTuple):
570 """A response for the SSH agent protocol.
572 Attributes:
573 code:
574 The desired response code.
575 payload:
576 The desired response payload.
578 """
580 code: _types.SSH_AGENT | int
581 """"""
582 payload: bytes
583 """"""
586# Vault configurations
587# ====================
590class ValidationSettings(NamedTuple):
591 """Validation settings for [`VaultTestConfig`][]s.
593 Attributes:
594 allow_unknown_settings:
595 See [`_types.validate_vault_config`][].
597 """
599 allow_unknown_settings: bool
600 """"""
603class VaultTestConfig(NamedTuple):
604 """A (not necessarily valid) sample vault config, plus metadata.
606 Attributes:
607 config:
608 The actual configuration object. Usually a [`dict`][].
609 comment:
610 An explanatory comment for what is wrong with this config,
611 or empty if the config is valid. This is intended as
612 a debugging message to be shown to the user (e.g. when an
613 assertion fails), not as an error message to
614 programmatically match against.
615 validation_settings:
616 See [`_types.validate_vault_config`][].
618 """
620 config: Any
621 """"""
622 comment: str
623 """"""
624 validation_settings: ValidationSettings | None
625 """"""
627 def is_valid(self, /) -> bool:
628 """Return true if this test config is valid."""
629 return not self.comment and self.validation_settings in {
630 None,
631 (True,),
632 }
634 def is_smudgable(self) -> bool:
635 """Return true if this vault test config can be effectively smudged.
637 A "smudged" test config is one where falsy values (in the
638 JavaScript sense) can be replaced by other falsy values without
639 changing the meaning of the config.
641 """
642 config = self.config 1aefgh
643 return bool( 1aefgh
644 isinstance(config, dict)
645 and ("global" not in config or isinstance(config["global"], dict))
646 and ("services" in config and isinstance(config["services"], dict))
647 and all(isinstance(x, dict) for x in config["services"].values())
648 and (config["services"] or config.get("global"))
649 )
651 def _test_id(self) -> Any: # pragma: no cover
652 """Return a test ID, e.g., for `pytest`."""
653 return self[1] or (self[0], self[1], self[2])
656# Data objects
657# ============
660# SSH agent socket provider data
661# ------------------------------
664ssh_auth_sock_on_posix_entry = _types.SSHAgentSocketProviderEntry(
665 socketprovider.SocketProvider.resolve(
666 _types.BuiltinSSHAgentSocketProvider.SSH_AUTH_SOCK_ON_POSIX
667 ),
668 _types.BuiltinSSHAgentSocketProvider.SSH_AUTH_SOCK_ON_POSIX,
669 (),
670)
671"""
672The standard [`_types.SSHAgentSocketProviderEntry`][] for the UNIX
673domain socket handler on POSIX systems.
674"""
676ssh_auth_sock_on_windows_entry = _types.SSHAgentSocketProviderEntry(
677 socketprovider.SocketProvider.resolve(
678 _types.BuiltinSSHAgentSocketProvider.SSH_AUTH_SOCK_ON_WINDOWS
679 ),
680 _types.BuiltinSSHAgentSocketProvider.SSH_AUTH_SOCK_ON_WINDOWS,
681 (),
682)
683"""
684The standard [`_types.SSHAgentSocketProviderEntry`][] for the Windows
685named pipe handler on The Annoying Operating System.
686"""
688faulty_entry_callable = _types.SSHAgentSocketProviderEntry(
689 (), # type: ignore[arg-type]
690 "tuple",
691 (),
692)
693"""
694A faulty [`_types.SSHAgentSocketProviderEntry`][]: the indicated handler
695is not a callable.
696"""
698faulty_entry_name_exists = _types.SSHAgentSocketProviderEntry(
699 socketprovider.SocketProvider.resolve(
700 _types.BuiltinSSHAgentSocketProvider.WINDOWS
701 ),
702 _types.BuiltinSSHAgentSocketProvider.POSIX,
703 (),
704)
705"""
706A faulty [`_types.SSHAgentSocketProviderEntry`][]: the indicated handler
707is already registered with a different callable.
708"""
710faulty_entry_alias_exists = _types.SSHAgentSocketProviderEntry(
711 socketprovider.SocketProvider.resolve(
712 _types.BuiltinSSHAgentSocketProvider.SSH_AUTH_SOCK_ON_POSIX
713 ),
714 _types.BuiltinSSHAgentSocketProvider.SSH_AUTH_SOCK_ON_POSIX,
715 (
716 _types.BuiltinSSHAgentSocketProvider.UNIX_DOMAIN,
717 _types.BuiltinSSHAgentSocketProvider.WINDOWS_NAMED_PIPE,
718 ),
719)
720"""
721A faulty [`_types.SSHAgentSocketProviderEntry`][]: the alias is already
722registered with a different callable.
723"""
725# SSH test keys
726# -------------
729ALL_KEYS: Mapping[str, SSHTestKey] = {
730 "ed25519": SSHTestKey(
731 private_key=rb"""-----BEGIN OPENSSH PRIVATE KEY-----
732b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
733QyNTUxOQAAACCBeIFoJtYCSF8P/zJIb+TBMIncHGpFBgnpCQ/7whJpdgAAAKDweO7H8Hju
734xwAAAAtzc2gtZWQyNTUxOQAAACCBeIFoJtYCSF8P/zJIb+TBMIncHGpFBgnpCQ/7whJpdg
735AAAEAbM/A869nkWZbe2tp3Dm/L6gitvmpH/aRZt8sBII3ExYF4gWgm1gJIXw//Mkhv5MEw
736idwcakUGCekJD/vCEml2AAAAG3Rlc3Qga2V5IHdpdGhvdXQgcGFzc3BocmFzZQEC
737-----END OPENSSH PRIVATE KEY-----
738""",
739 private_key_blob=bytes.fromhex("""
740 00 00 00 0b 73 73 68 2d 65 64 32 35 35 31 39
741 00 00 00 20
742 81 78 81 68 26 d6 02 48 5f 0f ff 32 48 6f e4 c1
743 30 89 dc 1c 6a 45 06 09 e9 09 0f fb c2 12 69 76
744 00 00 00 40
745 1b 33 f0 3c eb d9 e4 59 96 de da da 77 0e 6f cb
746 ea 08 ad be 6a 47 fd a4 59 b7 cb 01 20 8d c4 c5
747 81 78 81 68 26 d6 02 48 5f 0f ff 32 48 6f e4 c1
748 30 89 dc 1c 6a 45 06 09 e9 09 0f fb c2 12 69 76
749 00 00 00 1b 74 65 73 74 20 6b 65 79 20 77 69 74
750 68 6f 75 74 20 70 61 73 73 70 68 72 61 73 65
751"""),
752 public_key=rb"""ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIF4gWgm1gJIXw//Mkhv5MEwidwcakUGCekJD/vCEml2 test key without passphrase
753""",
754 public_key_data=bytes.fromhex("""
755 00 00 00 0b 73 73 68 2d 65 64 32 35 35 31 39
756 00 00 00 20
757 81 78 81 68 26 d6 02 48 5f 0f ff 32 48 6f e4 c1
758 30 89 dc 1c 6a 45 06 09 e9 09 0f fb c2 12 69 76
759"""),
760 expected_signatures={
761 SSHTestKeyDeterministicSignatureClass.SPEC: SSHTestKeyDeterministicSignature(
762 signature=bytes.fromhex("""
763 00 00 00 0b 73 73 68 2d 65 64 32 35 35 31 39
764 00 00 00 40
765 f0 98 19 80 6c 1a 97 d5 26 03 6e cc e3 65 8f 86
766 66 07 13 19 13 09 21 33 33 f9 e4 36 53 1d af fd
767 0d 08 1f ec f8 73 9b 8c 5f 55 39 16 7c 53 54 2c
768 1e 52 bb 30 ed 7f 89 e2 2f 69 51 55 d8 9e a6 02
769"""),
770 derived_passphrase=rb"""8JgZgGwal9UmA27M42WPhmYHExkTCSEzM/nkNlMdr/0NCB/s+HObjF9VORZ8U1QsHlK7MO1/ieIvaVFV2J6mAg==""",
771 ),
772 },
773 ),
774 # Currently only supported by PuTTY (which is deficient in other
775 # niceties of the SSH agent and the agent's client).
776 "ed448": SSHTestKey(
777 private_key=rb"""-----BEGIN OPENSSH PRIVATE KEY-----
778b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAAAlz
779c2gtZWQ0NDgAAAA54vZy009Wu8wExjvEb3hqtLz1GO/+d5vmGUbErWQ4AUO9mYLT
780zHJHc2m4s+yWzP29Cc3EcxizLG8AAAAA8BdhfCcXYXwnAAAACXNzaC1lZDQ0OAAA
781ADni9nLTT1a7zATGO8RveGq0vPUY7/53m+YZRsStZDgBQ72ZgtPMckdzabiz7JbM
782/b0JzcRzGLMsbwAAAAByM7GIMRvWJB3YD6SIpAF2uudX4ozZe0X917wPwiBrs373
7839TM1n94Nib6hrxGNmCk2iBQDe2KALPgA4vZy009Wu8wExjvEb3hqtLz1GO/+d5vm
784GUbErWQ4AUO9mYLTzHJHc2m4s+yWzP29Cc3EcxizLG8AAAAAG3Rlc3Qga2V5IHdp
785dGhvdXQgcGFzc3BocmFzZQECAwQFBgcICQ==
786-----END OPENSSH PRIVATE KEY-----
787""",
788 private_key_blob=bytes.fromhex("""
789 00 00 00 09 73 73 68 2d 65 64 34 34 38
790 00 00 00 39 e2 f6 72 d3 4f 56 bb cc 04
791 c6 3b c4 6f 78 6a b4 bc f5 18 ef fe 77 9b e6 19
792 46 c4 ad 64 38 01 43 bd 99 82 d3 cc 72 47 73 69
793 b8 b3 ec 96 cc fd bd 09 cd c4 73 18 b3 2c 6f 00
794 00 00 00 72 33 b1
795 88 31 1b d6 24 1d d8 0f a4 88 a4 01 76 ba e7 57
796 e2 8c d9 7b 45 fd d7 bc 0f c2 20 6b b3 7e f7 f5
797 33 35 9f de 0d 89 be a1 af 11 8d 98 29 36 88 14
798 03 7b 62 80 2c f8 00 e2 f6 72 d3 4f 56 bb cc 04
799 c6 3b c4 6f 78 6a b4 bc f5 18 ef fe 77 9b e6 19
800 46 c4 ad 64 38 01 43 bd 99 82 d3 cc 72 47 73 69
801 b8 b3 ec 96 cc fd bd 09 cd c4 73 18 b3 2c 6f 00
802 00 00 00 1b 74 65 73 74 20 6b 65 79 20 77 69
803 74 68 6f 75 74 20 70 61 73 73 70 68 72 61 73 65
804"""),
805 public_key=rb"""ssh-ed448 AAAACXNzaC1lZDQ0OAAAADni9nLTT1a7zATGO8RveGq0vPUY7/53m+YZRsStZDgBQ72ZgtPMckdzabiz7JbM/b0JzcRzGLMsbwA= test key without passphrase
806""",
807 public_key_data=bytes.fromhex("""
808 00 00 00 09 73 73 68 2d 65 64 34 34 38
809 00 00 00 39 e2 f6 72 d3 4f 56 bb cc 04
810 c6 3b c4 6f 78 6a b4 bc f5 18 ef fe 77 9b e6 19
811 46 c4 ad 64 38 01 43 bd 99 82 d3 cc 72 47 73 69
812 b8 b3 ec 96 cc fd bd 09 cd c4 73 18 b3 2c 6f 00
813 """),
814 expected_signatures={
815 SSHTestKeyDeterministicSignatureClass.SPEC: SSHTestKeyDeterministicSignature(
816 signature=bytes.fromhex("""
817 00 00 00 09 73 73 68 2d 65 64 34 34 38
818 00 00 00 72 06 86
819 f4 64 a4 a6 ba d9 c3 22 c4 93 49 99 fc 11 de 67
820 97 08 f2 d8 b7 3c 2c 13 e7 c5 1c 1e 92 a6 0e d8
821 2f 6d 81 03 82 00 e3 72 e4 32 6d 72 d2 6d 32 84
822 3f cc a9 1e 57 2c 00 9a b3 99 de 45 da ce 2e d1
823 db e5 89 f3 35 be 24 58 90 c6 ca 04 f0 db 88 80
824 db bd 77 7c 80 20 7f 3a 48 61 f6 1f ae a9 5e 53
825 7b e0 9d 93 1e ea dc eb b5 cd 56 4c ea 8f 08 00
826"""),
827 derived_passphrase=rb"""Bob0ZKSmutnDIsSTSZn8Ed5nlwjy2Lc8LBPnxRwekqYO2C9tgQOCAONy5DJtctJtMoQ/zKkeVywAmrOZ3kXazi7R2+WJ8zW+JFiQxsoE8NuIgNu9d3yAIH86SGH2H66pXlN74J2THurc67XNVkzqjwgA""",
828 ),
829 },
830 ),
831 "rsa": SSHTestKey(
832 private_key=rb"""-----BEGIN OPENSSH PRIVATE KEY-----
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
869-----END OPENSSH PRIVATE KEY-----
870""",
871 private_key_blob=bytes.fromhex("""
872 00 00 00 07 73 73 68 2d 72 73 61
873 00 00 01 81 00
874 b1 a1 ee e9 7b 38 71 5b 2e 0d 23 49 94 c0 aa a0
875 f5 60 98 38 04 be 22 3c 4d f5 e6 1c aa 97 dc 99
876 08 a8 8d cb b2 f5 7b 22 37 fc 58 27 53 bd e1 2a
877 ec 29 2e 66 12 26 b6 c4 79 d8 03 84 54 0a 14 f2
878 60 d7 0c da fe 9c 9e 70 50 fc df d5 42 1a 46 30
879 de d2 57 17 5b 84 a5 17 4d 61 42 c1 b8 c1 80 ee
880 ab 1b 21 c1 e9 6b 68 1f cb dd ed 33 84 3e df 8d
881 81 c5 f0 86 c5 b2 a1 a5 14 75 84 c0 eb 65 7e 18
882 5f 6f 12 6c 4c 68 2e 2e 6e 00 f3 f8 1d 10 90 f9
883 da b9 2a 0d c6 69 21 70 87 b4 96 c2 cd 6f 5a 42
884 95 9c b3 f3 c3 c3 9c a5 c2 5f f7 74 1e e3 7f 1c
885 9f ac 6c f8 3b 74 2b ce ca a1 58 4b 22 a7 de e6
886 3a 6c 25 ea a0 87 6e af 15 f3 1f 73 bb cf 43 fc
887 7f 9b 1b 98 a3 ab 18 62 8d b8 dc 55 45 b7 95 97
888 f0 ff de e0 cb d2 7a ac 6d f5 1c d6 ab e4 7f 06
889 c9 c2 d3 17 0b 82 15 ea 43 99 31 29 36 04 0b 2a
890 87 bc 78 f2 04 3e ae 16 1e 11 54 a2 f0 5d c2 5a
891 ce 07 25 0a 2a ac 6b 7b 2b d6 b7 98 24 a5 30 11
892 cf ef 4b b7 c3 a3 04 ed eb a6 a2 bc b1 95 4a 1f
893 7b 04 dd d7 b6 44 93 37 57 d3 c9 76 66 52 b3 66
894 fc 10 52 b7 3e c5 06 76 53 0f 33 da 67 d6 e9 38
895 b8 82 2d 29 60 66 a2 83 b2 9e e0 fc 2e 5e 9a 3f
896 0b 96 00 59 f7 97 c9 cb 2f 25 9d ae 69 84 63 31
897 d6 5e 24 63 40 9c 72 d4 18 b9 01 b1 cc 39 68 8f
898 00 00 00 03 01 00 01
899 00 00 01 7f
900 70 d5 58 4f e3 a6 e3 1f 7e 48 8b 5c cf 96 ce
901 07 21 88 3a 3c 96 50 7f 1f f6 b4 63 9e be 48 2e
902 ec 1a 6c 80 e0 bc 56 95 1b ec 4c d4 ed 61 58 00
903 ea cc c9 d2 11 c9 27 1d 19 13 60 4b 2a 60 fc a4
904 02 dc 45 be 33 85 12 1e f4 ea a4 54 27 e7 d5 66
905 4a 91 18 46 88 de 85 b2 58 a4 ce 85 c0 88 60 89
906 ad 38 db db d0 b3 af fc 74 36 1f 60 17 0a 87 aa
907 8d 24 f5 aa bf f1 4a e9 63 06 d7 01 f2 ec 31 b3
908 71 2a 68 ed 72 53 b4 28 66 90 dc 31 7f 69 94 7e
909 d1 99 cf 67 35 f6 5c 82 b9 e4 b4 f9 36 75 e5 f6
910 f9 8f c0 e6 dc dd 56 01 b5 21 ea 98 a7 a0 81 30
911 b3 4c ba 12 f4 38 f7 43 7a 18 01 a0 3b a3 c7 ea
912 e1 91 9d 60 a6 8d 70 71 42 c8 33 de 0d 2f b5 52
913 1c 13 d7 d0 b8 21 f5 3f b7 8f 51 d5 3f e6 27 30
914 0b e1 7c eb df 72 d2 e5 6c 9d 3a f9 36 06 44 03
915 2e 17 62 cf 08 06 4c fe 6d 05 13 20 2e ad 18 16
916 c4 08 cb 5e 6f b8 92 9d 86 00 95 e5 c3 cd 9d 78
917 39 10 f8 ff 1c 1c d4 fa b3 d6 47 47 96 12 cb 79
918 69 67 7e 79 f7 86 4c 38 b4 7c 2a a5 6f 86 02 46
919 17 a8 bd d3 5f 41 88 5f 75 48 3c 63 13 eb 29 e9
920 d3 46 7c df 16 fb ae 2d 1d d0 ef d9 ad 0c b2 8f
921 bc 42 3c b1 ee c4 e9 8b ef 84 8c b5 3c 23 2e f7
922 fd ee 01 f2 a6 d7 33 28 5e c8 0f d4 51 f8 0c b4
923 d2 92 86 1e ac 2e 5a c3 f6 1d 92 9b d4 45 4e e1
924 00 00 00 c0
925 26 1d ee ed 67 e7 8e 18 4a 65 86 c0 5b 84 ec 3c
926 d5 c3 32 b0 74 fe de f1 c8 04 20 16 69 28 ec 97
927 c4 4b 2a c9 48 b8 35 70 ef 90 30 e8 83 80 3e f3
928 b9 0f 51 4a 93 48 29 d3 ec 9c 89 da e6 97 a1 f7
929 bf 66 56 36 f6 1e 09 e2 92 3c 89 10 29 81 a4 b7
930 70 64 a8 57 ec c9 c8 be 02 b0 e6 59 d0 5c 76 e8
931 12 d5 82 6b 53 79 f2 5e df b2 bc f0 6e 2f 69 15
932 4b 94 a7 d7 52 85 73 5f 7e 69 54 0a 30 d1 b1 52
933 db 2b 90 ba fa 26 88 43 20 96 15 82 bc 99 ce 9d
934 a4 d9 08 a0 f2 9f f9 78 3e 10 90 88 15 0a 08 4e
935 a7 ae df 41 9c d7 e3 3e 7d d6 5c da 08 6a d1 be
936 97 2e d8 61 fe e1 c4 af 2f 1b eb c3 39 2a 09 4c
937 00 00 00 c1 00
938 f0 d6 2f 88 75 cb cf 57 fd ee fe af 4e fe 4c cb
939 a4 a3 b7 b5 b4 fc f6 c7 35 ce 18 d9 b0 33 63 0c
940 01 a5 b8 da fa 9f 7f 22 ab f5 d8 45 9b bb 51 32
941 fd 04 6f 84 80 55 5f 21 45 7b 5e c6 13 e5 ef 81
942 3d fd 77 55 2f 78 af 36 7b 99 a0 ac 3a 55 0b 5f
943 e5 5d 30 ed b3 06 e7 07 22 87 9c f5 15 25 45 9a
944 df 07 6d 41 d9 6e d8 18 c8 5b a6 86 b9 94 dd e5
945 28 94 3b 69 f1 e8 75 76 54 32 9d 1c 4c 56 ce 99
946 bc c9 81 2c ce db f3 44 ec 18 55 c2 6b dc 53 34
947 c3 24 63 0c 2a ec 41 3b ac 3d f5 82 83 29 12 a6
948 d0 f3 4b 14 3c f6 ea b5 a6 f4 b7 4d 4b 63 15 7d
949 5b 8f 31 3a 73 4f 6e 87 40 6e 29 15 a8 1e ab d7
950 00 00 00 c1 00
951 bc d1 05 77 59 17 c9 1b 48 16 b9 31 35 01 55 34
952 f3 80 a4 26 d4 2e fb da 02 7c 4f 4d 43 24 45 d9
953 b1 5b 4e bf b9 94 0b 5f e6 fd bc ba 1e 4e 2d 3f
954 2b c3 06 e1 a3 f6 11 ea e0 de dd 3e a1 ae b4 76
955 f5 ab 99 f4 00 3b a8 42 34 56 ec 15 f0 e5 0b c2
956 d8 40 03 f7 5c 5e c5 da 2b 20 0e 41 81 75 3e aa
957 5b 41 ab 3c c1 57 35 6d 17 bf a3 39 93 a3 7f 33
958 a5 69 35 fd 23 92 39 bd ec 9e 4d a4 f1 66 3d 57
959 5d 4c e2 6e d0 4d 74 c1 09 26 9e e2 7e e7 18 9a
960 86 00 03 01 3b 2b e5 65 59 a8 03 10 ad b2 f0 cb
961 5e f7 2f 44 f8 dd 2e 3b 68 fe 87 ce 6c 42 df d4
962 21 bd a2 13 fb e1 72 00 60 a7 ad 78 d9 69 d2 09
963 00 00 00 1b 74 65 73 74 20 6b 65 79 20 77 69
964 74 68 6f 75 74 20 70 61 73 73 70 68 72 61 73 65
965"""),
966 public_key=rb"""ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCxoe7pezhxWy4NI0mUwKqg9WCYOAS+IjxN9eYcqpfcmQiojcuy9XsiN/xYJ1O94SrsKS5mEia2xHnYA4RUChTyYNcM2v6cnnBQ/N/VQhpGMN7SVxdbhKUXTWFCwbjBgO6rGyHB6WtoH8vd7TOEPt+NgcXwhsWyoaUUdYTA62V+GF9vEmxMaC4ubgDz+B0QkPnauSoNxmkhcIe0lsLNb1pClZyz88PDnKXCX/d0HuN/HJ+sbPg7dCvOyqFYSyKn3uY6bCXqoIdurxXzH3O7z0P8f5sbmKOrGGKNuNxVRbeVl/D/3uDL0nqsbfUc1qvkfwbJwtMXC4IV6kOZMSk2BAsqh7x48gQ+rhYeEVSi8F3CWs4HJQoqrGt7K9a3mCSlMBHP70u3w6ME7eumoryxlUofewTd17ZEkzdX08l2ZlKzZvwQUrc+xQZ2Uw8z2mfW6Ti4gi0pYGaig7Ke4PwuXpo/C5YAWfeXycsvJZ2uaYRjMdZeJGNAnHLUGLkBscw5aI8= test key without passphrase
967""",
968 public_key_data=bytes.fromhex("""
969 00 00 00 07 73 73 68 2d 72 73 61
970 00 00 00 03 01 00 01
971 00 00 01 81 00
972 b1 a1 ee e9 7b 38 71 5b 2e 0d 23 49 94 c0 aa a0
973 f5 60 98 38 04 be 22 3c 4d f5 e6 1c aa 97 dc 99
974 08 a8 8d cb b2 f5 7b 22 37 fc 58 27 53 bd e1 2a
975 ec 29 2e 66 12 26 b6 c4 79 d8 03 84 54 0a 14 f2
976 60 d7 0c da fe 9c 9e 70 50 fc df d5 42 1a 46 30
977 de d2 57 17 5b 84 a5 17 4d 61 42 c1 b8 c1 80 ee
978 ab 1b 21 c1 e9 6b 68 1f cb dd ed 33 84 3e df 8d
979 81 c5 f0 86 c5 b2 a1 a5 14 75 84 c0 eb 65 7e 18
980 5f 6f 12 6c 4c 68 2e 2e 6e 00 f3 f8 1d 10 90 f9
981 da b9 2a 0d c6 69 21 70 87 b4 96 c2 cd 6f 5a 42
982 95 9c b3 f3 c3 c3 9c a5 c2 5f f7 74 1e e3 7f 1c
983 9f ac 6c f8 3b 74 2b ce ca a1 58 4b 22 a7 de e6
984 3a 6c 25 ea a0 87 6e af 15 f3 1f 73 bb cf 43 fc
985 7f 9b 1b 98 a3 ab 18 62 8d b8 dc 55 45 b7 95 97
986 f0 ff de e0 cb d2 7a ac 6d f5 1c d6 ab e4 7f 06
987 c9 c2 d3 17 0b 82 15 ea 43 99 31 29 36 04 0b 2a
988 87 bc 78 f2 04 3e ae 16 1e 11 54 a2 f0 5d c2 5a
989 ce 07 25 0a 2a ac 6b 7b 2b d6 b7 98 24 a5 30 11
990 cf ef 4b b7 c3 a3 04 ed eb a6 a2 bc b1 95 4a 1f
991 7b 04 dd d7 b6 44 93 37 57 d3 c9 76 66 52 b3 66
992 fc 10 52 b7 3e c5 06 76 53 0f 33 da 67 d6 e9 38
993 b8 82 2d 29 60 66 a2 83 b2 9e e0 fc 2e 5e 9a 3f
994 0b 96 00 59 f7 97 c9 cb 2f 25 9d ae 69 84 63 31
995 d6 5e 24 63 40 9c 72 d4 18 b9 01 b1 cc 39 68 8f
996"""),
997 expected_signatures={
998 SSHTestKeyDeterministicSignatureClass.SPEC: SSHTestKeyDeterministicSignature(
999 signature=bytes.fromhex("""
1000 00 00 00 07 73 73 68 2d 72 73 61
1001 00 00 01 80
1002 a2 10 7c 2e f6 bb 53 a8 74 2a a1 19 99 ad 81 be
1003 79 9c ed d6 9d 09 4e 6e c5 18 48 33 90 77 99 68
1004 f7 9e 03 5a cd 4e 18 eb 89 7d 85 a2 ee ae 4a 92
1005 f6 6f ce b9 fe 86 7f 2a 6b 31 da 6e 1a fe a2 a5
1006 88 b8 44 7f a1 76 73 b3 ec 75 b5 d0 a6 b9 15 97
1007 65 09 13 7d 94 21 d1 fb 5d 0f 8b 23 04 77 c2 c3
1008 55 22 b1 a0 09 8a f5 38 2a d6 7f 1b 87 29 a0 25
1009 d3 25 6f cb 64 61 07 98 dc 14 c5 84 f8 92 24 5e
1010 50 11 6b 49 e5 f0 cc 29 cb 29 a9 19 d8 a7 71 1f
1011 91 0b 05 b1 01 4b c2 5f 00 a5 b6 21 bf f8 2c 9d
1012 67 9b 47 3b 0a 49 6b 79 2d fc 1d ec 0c b0 e5 27
1013 22 d5 a9 f8 d3 c3 f9 df 48 68 e9 fb ef 3c dc 26
1014 bf cf ea 29 43 01 a6 e3 c5 51 95 f4 66 6d 8a 55
1015 e2 47 ec e8 30 45 4c ae 47 e7 c9 a4 21 8b 64 ba
1016 b6 88 f6 21 f8 73 b9 cb 11 a1 78 75 92 c6 5a e5
1017 64 fe ed 42 d9 95 99 e6 2b 6f 3c 16 3c 28 74 a4
1018 72 2f 0d 3f 2c 33 67 aa 35 19 8e e7 b5 11 2f b3
1019 f7 6a c5 02 e2 6f a3 42 e3 62 19 99 03 ea a5 20
1020 e7 a1 e3 bc c8 06 a3 b5 7c d6 76 5d df 6f 60 46
1021 83 2a 08 00 d6 d3 d9 a4 c1 41 8c f8 60 56 45 81
1022 da 3b a2 16 1f 9e 4e 75 83 17 da c3 53 c3 3e 19
1023 a4 1b bc d2 29 b8 78 61 2b 78 e6 b1 52 b0 d5 ec
1024 de 69 2c 48 62 d9 fd d1 9b 6b b0 49 db d3 ff 38
1025 e7 10 d9 2d ce 9f 0d 5e 09 7b 37 d2 7b c3 bf ce
1026"""),
1027 derived_passphrase=rb"""ohB8Lva7U6h0KqEZma2Bvnmc7dadCU5uxRhIM5B3mWj3ngNazU4Y64l9haLurkqS9m/Ouf6GfyprMdpuGv6ipYi4RH+hdnOz7HW10Ka5FZdlCRN9lCHR+10PiyMEd8LDVSKxoAmK9Tgq1n8bhymgJdMlb8tkYQeY3BTFhPiSJF5QEWtJ5fDMKcspqRnYp3EfkQsFsQFLwl8ApbYhv/gsnWebRzsKSWt5Lfwd7Ayw5Sci1an408P530ho6fvvPNwmv8/qKUMBpuPFUZX0Zm2KVeJH7OgwRUyuR+fJpCGLZLq2iPYh+HO5yxGheHWSxlrlZP7tQtmVmeYrbzwWPCh0pHIvDT8sM2eqNRmO57URL7P3asUC4m+jQuNiGZkD6qUg56HjvMgGo7V81nZd329gRoMqCADW09mkwUGM+GBWRYHaO6IWH55OdYMX2sNTwz4ZpBu80im4eGEreOaxUrDV7N5pLEhi2f3Rm2uwSdvT/zjnENktzp8NXgl7N9J7w7/O""",
1028 ),
1029 },
1030 ),
1031 "dsa1024": SSHTestKey(
1032 private_key=rb"""-----BEGIN OPENSSH PRIVATE KEY-----
1033b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsQAAAAdzc2gtZH
1034NzAAAAgQC7KAZXqBGNVLBQPrcMYAoNW54BhD8aIhe7BDWYzJcsaMt72VKSkguZ8+XR7nRa
10350C/ZsBi+uJp0dpxy9ZMTOWX4u5YPMeQcXEdGExZIfimGqSOAsy6fCld2IfJZJZExcCmhe9
1036Ssjsd3YSAPJRluOXFQc95MZoR5hMwlIDD8QzrE7QAAABUA99nOZOgd7aHMVGoXpUEBcn7H
1037ossAAACALr2Ag3hxM3rKdxzVUw8fX0VVPXO+3+Kr8hGe0Kc/7NwVaBVL1GQ8fenBuWynpA
1038UbH0wo3h1wkB/8hX6p+S8cnu5rIBlUuVNwLw/bIYohK98LfqTYK/V+g6KD+8m34wvEiXZm
1039qywY54n2bksch1Nqvj/tNpLzExSx/XS0kSM1aigAAACAbQNRPcVEuGDrEcf+xg5tgAejPX
1040BPXr/Jss+Chk64km3mirMYjAWyWYtVcgT+7hOYxtYRin8LyMLqKRmqa0Q5UrvDfChgLhvs
1041G9YSb/Mpw5qm8PiHSafwhkaz/te3+8hKogqoe7sd+tCF06IpJr5k70ACiNtRGqssNF8Elr
1042l1efYAAAH4swlfVrMJX1YAAAAHc3NoLWRzcwAAAIEAuygGV6gRjVSwUD63DGAKDVueAYQ/
1043GiIXuwQ1mMyXLGjLe9lSkpILmfPl0e50WtAv2bAYvriadHaccvWTEzll+LuWDzHkHFxHRh
1044MWSH4phqkjgLMunwpXdiHyWSWRMXApoXvUrI7Hd2EgDyUZbjlxUHPeTGaEeYTMJSAw/EM6
1045xO0AAAAVAPfZzmToHe2hzFRqF6VBAXJ+x6LLAAAAgC69gIN4cTN6yncc1VMPH19FVT1zvt
1046/iq/IRntCnP+zcFWgVS9RkPH3pwblsp6QFGx9MKN4dcJAf/IV+qfkvHJ7uayAZVLlTcC8P
10472yGKISvfC36k2Cv1foOig/vJt+MLxIl2ZqssGOeJ9m5LHIdTar4/7TaS8xMUsf10tJEjNW
1048ooAAAAgG0DUT3FRLhg6xHH/sYObYAHoz1wT16/ybLPgoZOuJJt5oqzGIwFslmLVXIE/u4T
1049mMbWEYp/C8jC6ikZqmtEOVK7w3woYC4b7BvWEm/zKcOapvD4h0mn8IZGs/7Xt/vISqIKqH
1050u7HfrQhdOiKSa+ZO9AAojbURqrLDRfBJa5dXn2AAAAFQDJHfenj4EJ9WkehpdJatPBlqCW
10510gAAABt0ZXN0IGtleSB3aXRob3V0IHBhc3NwaHJhc2UBAgMEBQYH
1052-----END OPENSSH PRIVATE KEY-----
1053""",
1054 private_key_blob=bytes.fromhex("""
1055 00 00 00 07 73 73 68 2d 64 73 73
1056 00 00 00 81 00
1057 bb 28 06 57 a8 11 8d 54 b0 50 3e b7 0c 60 0a 0d
1058 5b 9e 01 84 3f 1a 22 17 bb 04 35 98 cc 97 2c 68
1059 cb 7b d9 52 92 92 0b 99 f3 e5 d1 ee 74 5a d0 2f
1060 d9 b0 18 be b8 9a 74 76 9c 72 f5 93 13 39 65 f8
1061 bb 96 0f 31 e4 1c 5c 47 46 13 16 48 7e 29 86 a9
1062 23 80 b3 2e 9f 0a 57 76 21 f2 59 25 91 31 70 29
1063 a1 7b d4 ac 8e c7 77 61 20 0f 25 19 6e 39 71 50
1064 73 de 4c 66 84 79 84 cc 25 20 30 fc 43 3a c4 ed
1065 00 00 00 15 00 f7 d9 ce 64
1066 e8 1d ed a1 cc 54 6a 17 a5 41 01 72 7e c7 a2 cb
1067 00 00 00 80
1068 2e bd 80 83 78 71 33 7a ca 77 1c d5 53 0f 1f 5f
1069 45 55 3d 73 be df e2 ab f2 11 9e d0 a7 3f ec dc
1070 15 68 15 4b d4 64 3c 7d e9 c1 b9 6c a7 a4 05 1b
1071 1f 4c 28 de 1d 70 90 1f fc 85 7e a9 f9 2f 1c 9e
1072 ee 6b 20 19 54 b9 53 70 2f 0f db 21 8a 21 2b df
1073 0b 7e a4 d8 2b f5 7e 83 a2 83 fb c9 b7 e3 0b c4
1074 89 76 66 ab 2c 18 e7 89 f6 6e 4b 1c 87 53 6a be
1075 3f ed 36 92 f3 13 14 b1 fd 74 b4 91 23 35 6a 28
1076 00 00 00 80
1077 6d 03 51 3d c5 44 b8 60 eb 11 c7 fe c6 0e 6d 80
1078 07 a3 3d 70 4f 5e bf c9 b2 cf 82 86 4e b8 92 6d
1079 e6 8a b3 18 8c 05 b2 59 8b 55 72 04 fe ee 13 98
1080 c6 d6 11 8a 7f 0b c8 c2 ea 29 19 aa 6b 44 39 52
1081 bb c3 7c 28 60 2e 1b ec 1b d6 12 6f f3 29 c3 9a
1082 a6 f0 f8 87 49 a7 f0 86 46 b3 fe d7 b7 fb c8 4a
1083 a2 0a a8 7b bb 1d fa d0 85 d3 a2 29 26 be 64 ef
1084 40 02 88 db 51 1a ab 2c 34 5f 04 96 b9 75 79 f6
1085 00 00 00 15 00 c9 1d f7 a7
1086 8f 81 09 f5 69 1e 86 97 49 6a d3 c1 96 a0 96 d2
1087 00 00 00 1b 74 65 73 74 20 6b 65 79 20 77 69
1088 74 68 6f 75 74 20 70 61 73 73 70 68 72 61 73 65
1089"""),
1090 public_key=rb"""ssh-dss AAAAB3NzaC1kc3MAAACBALsoBleoEY1UsFA+twxgCg1bngGEPxoiF7sENZjMlyxoy3vZUpKSC5nz5dHudFrQL9mwGL64mnR2nHL1kxM5Zfi7lg8x5BxcR0YTFkh+KYapI4CzLp8KV3Yh8lklkTFwKaF71KyOx3dhIA8lGW45cVBz3kxmhHmEzCUgMPxDOsTtAAAAFQD32c5k6B3tocxUahelQQFyfseiywAAAIAuvYCDeHEzesp3HNVTDx9fRVU9c77f4qvyEZ7Qpz/s3BVoFUvUZDx96cG5bKekBRsfTCjeHXCQH/yFfqn5Lxye7msgGVS5U3AvD9shiiEr3wt+pNgr9X6DooP7ybfjC8SJdmarLBjnifZuSxyHU2q+P+02kvMTFLH9dLSRIzVqKAAAAIBtA1E9xUS4YOsRx/7GDm2AB6M9cE9ev8myz4KGTriSbeaKsxiMBbJZi1VyBP7uE5jG1hGKfwvIwuopGaprRDlSu8N8KGAuG+wb1hJv8ynDmqbw+IdJp/CGRrP+17f7yEqiCqh7ux360IXToikmvmTvQAKI21Eaqyw0XwSWuXV59g== test key without passphrase
1091""",
1092 public_key_data=bytes.fromhex("""
1093 00 00 00 07 73 73 68 2d 64 73 73
1094 00 00 00 81 00
1095 bb 28 06 57 a8 11 8d 54 b0 50 3e b7 0c 60 0a 0d
1096 5b 9e 01 84 3f 1a 22 17 bb 04 35 98 cc 97 2c 68
1097 cb 7b d9 52 92 92 0b 99 f3 e5 d1 ee 74 5a d0 2f
1098 d9 b0 18 be b8 9a 74 76 9c 72 f5 93 13 39 65 f8
1099 bb 96 0f 31 e4 1c 5c 47 46 13 16 48 7e 29 86 a9
1100 23 80 b3 2e 9f 0a 57 76 21 f2 59 25 91 31 70 29
1101 a1 7b d4 ac 8e c7 77 61 20 0f 25 19 6e 39 71 50
1102 73 de 4c 66 84 79 84 cc 25 20 30 fc 43 3a c4 ed
1103 00 00 00 15 00 f7 d9 ce 64
1104 e8 1d ed a1 cc 54 6a 17 a5 41 01 72 7e c7 a2 cb
1105 00 00 00 80
1106 2e bd 80 83 78 71 33 7a ca 77 1c d5 53 0f 1f 5f
1107 45 55 3d 73 be df e2 ab f2 11 9e d0 a7 3f ec dc
1108 15 68 15 4b d4 64 3c 7d e9 c1 b9 6c a7 a4 05 1b
1109 1f 4c 28 de 1d 70 90 1f fc 85 7e a9 f9 2f 1c 9e
1110 ee 6b 20 19 54 b9 53 70 2f 0f db 21 8a 21 2b df
1111 0b 7e a4 d8 2b f5 7e 83 a2 83 fb c9 b7 e3 0b c4
1112 89 76 66 ab 2c 18 e7 89 f6 6e 4b 1c 87 53 6a be
1113 3f ed 36 92 f3 13 14 b1 fd 74 b4 91 23 35 6a 28
1114 00 00 00 80
1115 6d 03 51 3d c5 44 b8 60 eb 11 c7 fe c6 0e 6d 80
1116 07 a3 3d 70 4f 5e bf c9 b2 cf 82 86 4e b8 92 6d
1117 e6 8a b3 18 8c 05 b2 59 8b 55 72 04 fe ee 13 98
1118 c6 d6 11 8a 7f 0b c8 c2 ea 29 19 aa 6b 44 39 52
1119 bb c3 7c 28 60 2e 1b ec 1b d6 12 6f f3 29 c3 9a
1120 a6 f0 f8 87 49 a7 f0 86 46 b3 fe d7 b7 fb c8 4a
1121 a2 0a a8 7b bb 1d fa d0 85 d3 a2 29 26 be 64 ef
1122 40 02 88 db 51 1a ab 2c 34 5f 04 96 b9 75 79 f6
1123"""),
1124 expected_signatures={
1125 SSHTestKeyDeterministicSignatureClass.RFC_6979: SSHTestKeyDeterministicSignature(
1126 signature=bytes.fromhex("""
1127 00 00 00 07 73 73 68 2d 64 73 73
1128 00 00 00 28 11 5f 4d 13 c2 ee 61 97
1129 1e f6 23 14 3b 2b dd cf 06 c0 71 13 cc ac 34 19
1130 ad 36 8d 79 aa 25 fb 5e 4f ea fe 6b 5b fa 57 42
1131"""),
1132 derived_passphrase=rb"""EV9NE8LuYZce9iMUOyvdzwbAcRPMrDQZrTaNeaol+15P6v5rW/pXQg==""",
1133 signature_class=SSHTestKeyDeterministicSignatureClass.RFC_6979,
1134 ),
1135 SSHTestKeyDeterministicSignatureClass.Pageant_068_080: SSHTestKeyDeterministicSignature(
1136 signature=bytes.fromhex("""
1137 00 00 00 07 73 73 68 2d 64 73 73
1138 00 00 00 28 0b f7 a8 ab 89 f5 b6 c4
1139 1c 9b 78 2c 46 35 69 e2 88 b7 eb 55 37 48 7f 6d
1140 49 a1 e6 de 58 1a 04 eb e6 28 99 0e 3c fd 3b 48
1141"""),
1142 derived_passphrase=rb"""C/eoq4n1tsQcm3gsRjVp4oi361U3SH9tSaHm3lgaBOvmKJkOPP07SA==""",
1143 signature_class=SSHTestKeyDeterministicSignatureClass.Pageant_068_080,
1144 ),
1145 },
1146 ),
1147 "ecdsa256": SSHTestKey(
1148 private_key=rb"""-----BEGIN OPENSSH PRIVATE KEY-----
1149b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
11501zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTLbU0zDwsk2Dvp+VYIrsNVf5gWwz2S
11513SZ8TbxiQRkpnGSVqyIoHJOJc+NQItAa7xlJ/8Z6gfz57Z3apUkaMJm6AAAAuKeY+YinmP
1152mIAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMttTTMPCyTYO+n5
1153Vgiuw1V/mBbDPZLdJnxNvGJBGSmcZJWrIigck4lz41Ai0BrvGUn/xnqB/PntndqlSRowmb
1154oAAAAhAKIl/3n0pKVIxpZkXTGtii782Qr4yIcvHdpxjO/QsIqKAAAAG3Rlc3Qga2V5IHdp
1155dGhvdXQgcGFzc3BocmFzZQECAwQ=
1156-----END OPENSSH PRIVATE KEY-----
1157""",
1158 private_key_blob=bytes.fromhex("""
1159 00 00 00 13 65 63 64
1160 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 36
1161 00 00 00 08 6e 69 73 74 70 32 35 36
1162 00 00 00 41 04
1163 cb 6d 4d 33 0f 0b 24 d8 3b e9 f9 56 08 ae c3 55
1164 7f 98 16 c3 3d 92 dd 26 7c 4d bc 62 41 19 29 9c
1165 64 95 ab 22 28 1c 93 89 73 e3 50 22 d0 1a ef 19
1166 49 ff c6 7a 81 fc f9 ed 9d da a5 49 1a 30 99 ba
1167 00 00 00 21 00
1168 a2 25 ff 79 f4 a4 a5 48 c6 96 64 5d 31 ad 8a 2e
1169 fc d9 0a f8 c8 87 2f 1d da 71 8c ef d0 b0 8a 8a
1170 00 00 00 1b 74 65 73 74 20 6b 65 79 20 77 69
1171 74 68 6f 75 74 20 70 61 73 73 70 68 72 61 73 65
1172"""),
1173 public_key=rb"""ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMttTTMPCyTYO+n5Vgiuw1V/mBbDPZLdJnxNvGJBGSmcZJWrIigck4lz41Ai0BrvGUn/xnqB/PntndqlSRowmbo= test key without passphrase
1174""",
1175 public_key_data=bytes.fromhex("""
1176 00 00 00 13 65 63 64
1177 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 36
1178 00 00 00 08 6e 69 73 74 70 32 35 36
1179 00 00 00 41 04
1180 cb 6d 4d 33 0f 0b 24 d8 3b e9 f9 56 08 ae c3 55
1181 7f 98 16 c3 3d 92 dd 26 7c 4d bc 62 41 19 29 9c
1182 64 95 ab 22 28 1c 93 89 73 e3 50 22 d0 1a ef 19
1183 49 ff c6 7a 81 fc f9 ed 9d da a5 49 1a 30 99 ba
1184"""),
1185 expected_signatures={
1186 SSHTestKeyDeterministicSignatureClass.RFC_6979: SSHTestKeyDeterministicSignature(
1187 signature=bytes.fromhex("""
1188 00 00 00 13 65 63 64
1189 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 36
1190 00 00 00 49
1191 00 00 00 20
1192 22 ad 23 8a 9c 5d ca 4e ea 73 e7 29 77 ab a8 b2
1193 2e 01 d8 de 11 ae c9 b3 57 ce d5 84 9c 85 73 eb
1194 00 00 00 21 00
1195 9b 1a cb dd 45 89 f0 37 95 9c a2 d8 ac c3 f7 71
1196 55 33 50 86 9e cb 3a 95 e4 68 80 1a 9d d6 d5 bc
1197"""),
1198 derived_passphrase=rb"""AAAAICKtI4qcXcpO6nPnKXerqLIuAdjeEa7Js1fO1YSchXPrAAAAIQCbGsvdRYnwN5Wcotisw/dxVTNQhp7LOpXkaIAandbVvA==""",
1199 signature_class=SSHTestKeyDeterministicSignatureClass.RFC_6979,
1200 ),
1201 SSHTestKeyDeterministicSignatureClass.Pageant_068_080: SSHTestKeyDeterministicSignature(
1202 signature=bytes.fromhex("""
1203 00 00 00 13 65 63 64
1204 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 32 35 36
1205 00 00 00 49
1206 00 00 00 21 00
1207 b7 9e 4f ec ec 9b 77 dd 12 d9 43 a2 f5 bf b5 34
1208 91 e0 89 44 e6 20 48 36 fa 75 22 77 86 38 de 21
1209 00 00 00 20
1210 3f d8 04 0f fa f5 bc d2 26 e0 4c 0c 77 5d 0e 08
1211 ec 30 04 8e 42 58 41 96 f6 7e 4f d2 14 39 f4 87
1212"""),
1213 derived_passphrase=rb"""AAAAIQC3nk/s7Jt33RLZQ6L1v7U0keCJROYgSDb6dSJ3hjjeIQAAACA/2AQP+vW80ibgTAx3XQ4I7DAEjkJYQZb2fk/SFDn0hw==""",
1214 signature_class=SSHTestKeyDeterministicSignatureClass.Pageant_068_080,
1215 ),
1216 },
1217 ),
1218 "ecdsa384": SSHTestKey(
1219 private_key=rb"""-----BEGIN OPENSSH PRIVATE KEY-----
1220b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAiAAAABNlY2RzYS
12211zaGEyLW5pc3RwMzg0AAAACG5pc3RwMzg0AAAAYQSgkOjkAvq7v5vHuj3KBL4/EAWcn5hZ
1222DyKcbyV0eBMGFq7hKXQlZqIahLVqeMR0QqmkxNJ2rly2VHcXneq3vZ+9fIsWCOdYk5WP3N
1223ZPzv911Xn7wbEkC7QndD5zKlm4pBUAAADomhj+IZoY/iEAAAATZWNkc2Etc2hhMi1uaXN0
1224cDM4NAAAAAhuaXN0cDM4NAAAAGEEoJDo5AL6u7+bx7o9ygS+PxAFnJ+YWQ8inG8ldHgTBh
1225au4Sl0JWaiGoS1anjEdEKppMTSdq5ctlR3F53qt72fvXyLFgjnWJOVj9zWT87/ddV5+8Gx
1226JAu0J3Q+cypZuKQVAAAAMQD5sTy8p+B1cn/DhOmXquui1BcxvASqzzevkBlbQoBa73y04B
12272OdqVOVRkwZWRROz0AAAAbdGVzdCBrZXkgd2l0aG91dCBwYXNzcGhyYXNlAQIDBA==
1228-----END OPENSSH PRIVATE KEY-----
1229""",
1230 private_key_blob=bytes.fromhex("""
1231 00 00 00 13 65 63 64
1232 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34
1233 00 00 00 08 6e 69 73 74 70 33 38 34
1234 00 00 00 61 04
1235 a0 90 e8 e4 02 fa bb bf 9b c7 ba 3d ca 04 be 3f
1236 10 05 9c 9f 98 59 0f 22 9c 6f 25 74 78 13 06 16
1237 ae e1 29 74 25 66 a2 1a 84 b5 6a 78 c4 74 42 a9
1238 a4 c4 d2 76 ae 5c b6 54 77 17 9d ea b7 bd 9f bd
1239 7c 8b 16 08 e7 58 93 95 8f dc d6 4f ce ff 75 d5
1240 79 fb c1 b1 24 0b b4 27 74 3e 73 2a 59 b8 a4 15
1241 00 00 00 31 00
1242 f9 b1 3c bc a7 e0 75 72 7f c3 84 e9 97 aa eb a2
1243 d4 17 31 bc 04 aa cf 37 af 90 19 5b 42 80 5a ef
1244 7c b4 e0 1d 8e 76 a5 4e 55 19 30 65 64 51 3b 3d
1245 00 00 00 1b 74 65 73 74 20 6b 65 79 20 77 69
1246 74 68 6f 75 74 20 70 61 73 73 70 68 72 61 73 65
1247"""),
1248 public_key=rb"""ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBKCQ6OQC+ru/m8e6PcoEvj8QBZyfmFkPIpxvJXR4EwYWruEpdCVmohqEtWp4xHRCqaTE0nauXLZUdxed6re9n718ixYI51iTlY/c1k/O/3XVefvBsSQLtCd0PnMqWbikFQ== test key without passphrase
1249""",
1250 public_key_data=bytes.fromhex("""
1251 00 00 00 13 65 63 64
1252 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34
1253 00 00 00 08 6e 69 73 74 70 33 38 34
1254 00 00 00 61 04
1255 a0 90 e8 e4 02 fa bb bf 9b c7 ba 3d ca 04 be 3f
1256 10 05 9c 9f 98 59 0f 22 9c 6f 25 74 78 13 06 16
1257 ae e1 29 74 25 66 a2 1a 84 b5 6a 78 c4 74 42 a9
1258 a4 c4 d2 76 ae 5c b6 54 77 17 9d ea b7 bd 9f bd
1259 7c 8b 16 08 e7 58 93 95 8f dc d6 4f ce ff 75 d5
1260 79 fb c1 b1 24 0b b4 27 74 3e 73 2a 59 b8 a4 15
1261"""),
1262 expected_signatures={
1263 SSHTestKeyDeterministicSignatureClass.RFC_6979: SSHTestKeyDeterministicSignature(
1264 signature=bytes.fromhex("""
1265 00 00 00 13 65 63 64
1266 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34
1267 00 00 00 68
1268 00 00 00 30
1269 78 e1 a8 f5 8c d2 7a 21 e5 a2 ca e6 d0 1a 19 f8
1270 3a 1c 39 7e 71 a0 e6 7e 93 83 49 95 05 01 d0 3e
1271 23 22 cd 09 63 7f 7c 6c b0 97 44 6d 7e 48 39 87
1272 00 00 00 30
1273 10 ee 85 51 77 2b 91 2c e9 42 79 66 59 8a a2 c0
1274 d2 c8 8a 8f 2f 8f 33 87 9e 12 54 e4 da 02 f9 e7
1275 95 f5 82 6f 82 2b 38 6d 6e 5d 17 15 ac 12 e7 62
1276"""),
1277 derived_passphrase=rb"""AAAAMHjhqPWM0noh5aLK5tAaGfg6HDl+caDmfpODSZUFAdA+IyLNCWN/fGywl0Rtfkg5hwAAADAQ7oVRdyuRLOlCeWZZiqLA0siKjy+PM4eeElTk2gL555X1gm+CKzhtbl0XFawS52I=""",
1278 signature_class=SSHTestKeyDeterministicSignatureClass.RFC_6979,
1279 ),
1280 SSHTestKeyDeterministicSignatureClass.Pageant_068_080: SSHTestKeyDeterministicSignature(
1281 signature=bytes.fromhex("""
1282 00 00 00 13 65 63 64
1283 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 33 38 34
1284 00 00 00 69
1285 00 00 00 30
1286 4b 3e b7 22 c2 87 77 6d e0 3e f5 05 75 36 b6 0f
1287 cd 9f a4 49 c7 48 ef 76 fd ea 4b 49 e3 b1 f2 22
1288 d5 41 22 d7 96 b2 29 70 ff bb 81 97 27 e2 35 60
1289 00 00 00 31 00
1290 c8 a4 d8 62 fe f2 a6 63 97 98 08 c7 39 24 b2 55
1291 0a b8 e7 79 ab a6 62 96 3e cc ea 73 e2 fb dc 46
1292 d6 25 b9 c8 0c e8 3e 33 91 51 78 25 a8 c5 46 85
1293"""),
1294 derived_passphrase=rb"""AAAAMEs+tyLCh3dt4D71BXU2tg/Nn6RJx0jvdv3qS0njsfIi1UEi15ayKXD/u4GXJ+I1YAAAADEAyKTYYv7ypmOXmAjHOSSyVQq453mrpmKWPszqc+L73EbWJbnIDOg+M5FReCWoxUaF""",
1295 signature_class=SSHTestKeyDeterministicSignatureClass.Pageant_068_080,
1296 ),
1297 },
1298 ),
1299 "ecdsa521": SSHTestKey(
1300 private_key=rb"""-----BEGIN OPENSSH PRIVATE KEY-----
1301b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAArAAAABNlY2RzYS
13021zaGEyLW5pc3RwNTIxAAAACG5pc3RwNTIxAAAAhQQASVOdwDznmlcGqiLvFtYeVtrAEiVz
1303iIfsL7jEM8Utu/m8WSkPFQtjwqdFw+WfZ0mi6qMbEFgi/ELzZSKVteCSbcMAhqAkOMFKiD
1304u4bxvsM6bT02Ru7q2yT41ySyGhUD0QySBnI6Ckt/wnQ1TEpj8zDKiRErxs9e6QLGElNRkz
1305LPMs+mMAAAEY2FXeh9hV3ocAAAATZWNkc2Etc2hhMi1uaXN0cDUyMQAAAAhuaXN0cDUyMQ
1306AAAIUEAElTncA855pXBqoi7xbWHlbawBIlc4iH7C+4xDPFLbv5vFkpDxULY8KnRcPln2dJ
1307ouqjGxBYIvxC82UilbXgkm3DAIagJDjBSog7uG8b7DOm09Nkbu6tsk+NckshoVA9EMkgZy
1308OgpLf8J0NUxKY/MwyokRK8bPXukCxhJTUZMyzzLPpjAAAAQSFqUmKK7lGQzxT6GKZSLDju
1309U3otwLYnuj+/5AdzuB/zotu95UdFv9I2DNXzd9E4WAyz6IqBBNcsMkxrzHAdqsYDAAAAG3
1310Rlc3Qga2V5IHdpdGhvdXQgcGFzc3BocmFzZQ==
1311-----END OPENSSH PRIVATE KEY-----
1312""",
1313 private_key_blob=bytes.fromhex("""
1314 00 00 00 13 65 63 64
1315 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31
1316 00 00 00 08 6e 69 73 74 70 35 32 31
1317 00 00 00 85 04 00 49 53 9d
1318 c0 3c e7 9a 57 06 aa 22 ef 16 d6 1e 56 da c0 12
1319 25 73 88 87 ec 2f b8 c4 33 c5 2d bb f9 bc 59 29
1320 0f 15 0b 63 c2 a7 45 c3 e5 9f 67 49 a2 ea a3 1b
1321 10 58 22 fc 42 f3 65 22 95 b5 e0 92 6d c3 00 86
1322 a0 24 38 c1 4a 88 3b b8 6f 1b ec 33 a6 d3 d3 64
1323 6e ee ad b2 4f 8d 72 4b 21 a1 50 3d 10 c9 20 67
1324 23 a0 a4 b7 fc 27 43 54 c4 a6 3f 33 0c a8 91 12
1325 bc 6c f5 ee 90 2c 61 25 35 19 33 2c f3 2c fa 63
1326 00 00 00 41 21
1327 6a 52 62 8a ee 51 90 cf 14 fa 18 a6 52 2c 38 ee
1328 53 7a 2d c0 b6 27 ba 3f bf e4 07 73 b8 1f f3 a2
1329 db bd e5 47 45 bf d2 36 0c d5 f3 77 d1 38 58 0c
1330 b3 e8 8a 81 04 d7 2c 32 4c 6b cc 70 1d aa c6 03
1331 00 00 00 1b 74 65 73 74 20 6b 65 79 20 77 69
1332 74 68 6f 75 74 20 70 61 73 73 70 68 72 61 73 65
1333"""),
1334 public_key=rb"""ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBABJU53APOeaVwaqIu8W1h5W2sASJXOIh+wvuMQzxS27+bxZKQ8VC2PCp0XD5Z9nSaLqoxsQWCL8QvNlIpW14JJtwwCGoCQ4wUqIO7hvG+wzptPTZG7urbJPjXJLIaFQPRDJIGcjoKS3/CdDVMSmPzMMqJESvGz17pAsYSU1GTMs8yz6Yw== test key without passphrase
1335""",
1336 public_key_data=bytes.fromhex("""
1337 00 00 00 13 65 63 64
1338 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31
1339 00 00 00 08 6e 69 73 74 70 35 32 31
1340 00 00 00 85 04 00 49 53 9d
1341 c0 3c e7 9a 57 06 aa 22 ef 16 d6 1e 56 da c0 12
1342 25 73 88 87 ec 2f b8 c4 33 c5 2d bb f9 bc 59 29
1343 0f 15 0b 63 c2 a7 45 c3 e5 9f 67 49 a2 ea a3 1b
1344 10 58 22 fc 42 f3 65 22 95 b5 e0 92 6d c3 00 86
1345 a0 24 38 c1 4a 88 3b b8 6f 1b ec 33 a6 d3 d3 64
1346 6e ee ad b2 4f 8d 72 4b 21 a1 50 3d 10 c9 20 67
1347 23 a0 a4 b7 fc 27 43 54 c4 a6 3f 33 0c a8 91 12
1348 bc 6c f5 ee 90 2c 61 25 35 19 33 2c f3 2c fa 63
1349"""),
1350 expected_signatures={
1351 SSHTestKeyDeterministicSignatureClass.RFC_6979: SSHTestKeyDeterministicSignature(
1352 signature=bytes.fromhex("""
1353 00 00 00 13 65 63 64
1354 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31
1355 00 00 00 8b
1356 00 00 00 42 01 d8
1357 ea c2 1e 55 c6 9e dd 4b 00 ed 1b 93 19 cc 9b 74
1358 27 44 c0 c0 e3 5b 3d 81 15 00 12 cc 07 89 54 97
1359 ec 60 42 ad e6 40 c1 c6 5f c0 1b c3 0a 8e 58 6e
1360 da 3f a9 57 90 04 79 46 1d 48 bb 19 67 e9 65 19
1361 00 00 00 41 7d
1362 58 e0 2e d7 86 2e 36 8c 1a 44 23 af 19 e7 51 97
1363 bb fb 32 90 a1 35 bb 88 d7 b5 22 37 b3 99 ba e4
1364 a7 9d 2d 56 14 0a f5 68 f5 cc 38 84 e9 b6 c6 71
1365 7a 3b 87 e7 7a b1 37 e7 1d e6 80 96 d1 a6 1e bc
1366"""),
1367 derived_passphrase=rb"""AAAAQgHY6sIeVcae3UsA7RuTGcybdCdEwMDjWz2BFQASzAeJVJfsYEKt5kDBxl/AG8MKjlhu2j+pV5AEeUYdSLsZZ+llGQAAAEF9WOAu14YuNowaRCOvGedRl7v7MpChNbuI17UiN7OZuuSnnS1WFAr1aPXMOITptsZxejuH53qxN+cd5oCW0aYevA==""",
1368 signature_class=SSHTestKeyDeterministicSignatureClass.RFC_6979,
1369 ),
1370 SSHTestKeyDeterministicSignatureClass.Pageant_068_080: SSHTestKeyDeterministicSignature(
1371 signature=bytes.fromhex("""
1372 00 00 00 13 65 63 64
1373 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 35 32 31
1374 00 00 00 8c
1375 00 00 00 42 01 ce
1376 fe 9d 66 b6 01 76 2e 86 c2 ab 68 62 73 44 05 23
1377 fd d1 79 07 fc 45 f5 c0 83 36 88 61 d4 04 79 90
1378 b0 ef 8b 3c b5 55 0e cc 26 6b a0 3e 6a 04 48 ca
1379 e4 6a a5 a0 cf 91 5f 71 6f 37 9a 0f 6b a9 fb 9b
1380 00 00 00 42 01 6d
1381 21 77 c6 13 fa ea ac de 90 19 24 5a d2 61 39 d9
1382 66 9b 86 1a 41 04 58 a2 9b b8 93 b6 6f 82 23 f2
1383 01 23 c7 ff 5a d3 86 95 0f da 28 f9 3b e3 9c 27
1384 e7 b2 d7 66 4e 5f 38 36 4c 8c be 76 4e fa 0a 2d
1385"""),
1386 derived_passphrase=rb"""AAAAQgHO/p1mtgF2LobCq2hic0QFI/3ReQf8RfXAgzaIYdQEeZCw74s8tVUOzCZroD5qBEjK5GqloM+RX3FvN5oPa6n7mwAAAEIBbSF3xhP66qzekBkkWtJhOdlmm4YaQQRYopu4k7ZvgiPyASPH/1rThpUP2ij5O+OcJ+ey12ZOXzg2TIy+dk76Ci0=""",
1387 signature_class=SSHTestKeyDeterministicSignatureClass.Pageant_068_080,
1388 ),
1389 },
1390 ),
1391}
1392"""The master list of SSH test keys."""
1393SUPPORTED_KEYS: Mapping[str, SSHTestKey] = {
1394 k: v for k, v in ALL_KEYS.items() if v.is_suitable()
1395}
1396"""The subset of SSH test keys suitable for use with vault.
1398Suitability is tested -- via [SSHTestKey.is_suitable][], then
1399[vault.Vault.is_suitable_ssh_key][] -- via an internal whitelist, not
1400via the presence or absence of a specific expected signature class.
1402"""
1403UNSUITABLE_KEYS: Mapping[str, SSHTestKey] = {
1404 k: v for k, v in ALL_KEYS.items() if not v.is_suitable()
1405}
1406"""The subset of SSH test keys not suitable for use with vault.
1408Suitability is tested -- via [SSHTestKey.is_suitable][], then
1409[vault.Vault.is_suitable_ssh_key][] -- via an internal whitelist, not
1410via the presence or absence of a specific expected signature class.
1412"""
1415# Vault test configurations
1416# -------------------------
1419TEST_CONFIGS: list[VaultTestConfig] = [
1420 VaultTestConfig(None, "not a dict", None),
1421 VaultTestConfig({}, "missing required keys", None),
1422 VaultTestConfig(
1423 {"global": None, "services": {}}, "bad config value: global", None
1424 ),
1425 VaultTestConfig(
1426 {"global": {"key": 123}, "services": {}},
1427 "bad config value: global.key",
1428 None,
1429 ),
1430 VaultTestConfig(
1431 {"global": {"phrase": "abc", "key": "..."}, "services": {}},
1432 "",
1433 None,
1434 ),
1435 VaultTestConfig({"services": None}, "bad config value: services", None),
1436 VaultTestConfig(
1437 {"services": {"1": {}, 2: {}}}, 'bad config value: services."2"', None
1438 ),
1439 VaultTestConfig(
1440 {"services": {"1": {}, "2": 2}}, 'bad config value: services."2"', None
1441 ),
1442 VaultTestConfig(
1443 {"services": {"sv": {"notes": ["sentinel", "list"]}}},
1444 "bad config value: services.sv.notes",
1445 None,
1446 ),
1447 VaultTestConfig(
1448 {"services": {"sv": {"notes": "blah blah blah"}}}, "", None
1449 ),
1450 VaultTestConfig(
1451 {"services": {"sv": {"length": "200"}}},
1452 "bad config value: services.sv.length",
1453 None,
1454 ),
1455 VaultTestConfig(
1456 {"services": {"sv": {"length": 0.5}}},
1457 "bad config value: services.sv.length",
1458 None,
1459 ),
1460 VaultTestConfig(
1461 {"services": {"sv": {"length": ["sentinel", "list"]}}},
1462 "bad config value: services.sv.length",
1463 None,
1464 ),
1465 VaultTestConfig(
1466 {"services": {"sv": {"length": -10}}},
1467 "bad config value: services.sv.length",
1468 None,
1469 ),
1470 VaultTestConfig(
1471 {"services": {"sv": {"lower": "10"}}},
1472 "bad config value: services.sv.lower",
1473 None,
1474 ),
1475 VaultTestConfig(
1476 {"services": {"sv": {"upper": -10}}},
1477 "bad config value: services.sv.upper",
1478 None,
1479 ),
1480 VaultTestConfig(
1481 {"services": {"sv": {"number": ["sentinel", "list"]}}},
1482 "bad config value: services.sv.number",
1483 None,
1484 ),
1485 VaultTestConfig(
1486 {
1487 "global": {"phrase": "my secret phrase"},
1488 "services": {"sv": {"length": 10}},
1489 },
1490 "",
1491 None,
1492 ),
1493 VaultTestConfig(
1494 {"services": {"sv": {"length": 10, "phrase": "..."}}}, "", None
1495 ),
1496 VaultTestConfig(
1497 {"services": {"sv": {"length": 10, "key": "..."}}}, "", None
1498 ),
1499 VaultTestConfig(
1500 {"services": {"sv": {"upper": 10, "key": "..."}}}, "", None
1501 ),
1502 VaultTestConfig(
1503 {"services": {"sv": {"phrase": "abc", "key": "..."}}}, "", None
1504 ),
1505 VaultTestConfig(
1506 {
1507 "global": {"phrase": "abc"},
1508 "services": {"sv": {"phrase": "abc", "length": 10}},
1509 },
1510 "",
1511 None,
1512 ),
1513 VaultTestConfig(
1514 {
1515 "global": {"key": "..."},
1516 "services": {"sv": {"phrase": "abc", "length": 10}},
1517 },
1518 "",
1519 None,
1520 ),
1521 VaultTestConfig(
1522 {
1523 "global": {"key": "..."},
1524 "services": {"sv": {"phrase": "abc", "key": "...", "length": 10}},
1525 },
1526 "",
1527 None,
1528 ),
1529 VaultTestConfig(
1530 {
1531 "global": {"key": "..."},
1532 "services": {
1533 "sv1": {"phrase": "abc", "length": 10, "upper": 1},
1534 "sv2": {"length": 10, "repeat": 1, "lower": 1},
1535 },
1536 },
1537 "",
1538 None,
1539 ),
1540 VaultTestConfig(
1541 {
1542 "global": {"key": "...", "unicode_normalization_form": "NFC"},
1543 "services": {
1544 "sv1": {"phrase": "abc", "length": 10, "upper": 1},
1545 "sv2": {"length": 10, "repeat": 1, "lower": 1},
1546 },
1547 },
1548 "",
1549 None,
1550 ),
1551 VaultTestConfig(
1552 {
1553 "global": {"key": "...", "unicode_normalization_form": True},
1554 "services": {},
1555 },
1556 "bad config value: global.unicode_normalization_form",
1557 None,
1558 ),
1559 VaultTestConfig(
1560 {
1561 "global": {"key": "...", "unicode_normalization_form": "NFC"},
1562 "services": {
1563 "sv1": {"phrase": "abc", "length": 10, "upper": 1},
1564 "sv2": {"length": 10, "repeat": 1, "lower": 1},
1565 },
1566 },
1567 "",
1568 ValidationSettings(True),
1569 ),
1570 VaultTestConfig(
1571 {
1572 "global": {"key": "...", "unicode_normalization_form": "NFC"},
1573 "services": {
1574 "sv1": {"phrase": "abc", "length": 10, "upper": 1},
1575 "sv2": {"length": 10, "repeat": 1, "lower": 1},
1576 },
1577 },
1578 "extension/unknown key: .global.unicode_normalization_form",
1579 ValidationSettings(False),
1580 ),
1581 VaultTestConfig(
1582 {
1583 "global": {"key": "...", "unknown_key": True},
1584 "services": {
1585 "sv1": {"phrase": "abc", "length": 10, "upper": 1},
1586 "sv2": {"length": 10, "repeat": 1, "lower": 1},
1587 },
1588 },
1589 "",
1590 ValidationSettings(True),
1591 ),
1592 VaultTestConfig(
1593 {
1594 "global": {"key": "...", "unknown_key": True},
1595 "services": {
1596 "sv1": {"phrase": "abc", "length": 10, "upper": 1},
1597 "sv2": {"length": 10, "repeat": 1, "lower": 1},
1598 },
1599 },
1600 "unknown key: .global.unknown_key",
1601 ValidationSettings(False),
1602 ),
1603 VaultTestConfig(
1604 {
1605 "global": {"key": "..."},
1606 "services": {
1607 "sv1": {"phrase": "abc", "length": 10, "upper": 1},
1608 "sv2": {
1609 "length": 10,
1610 "repeat": 1,
1611 "lower": 1,
1612 "unknown_key": True,
1613 },
1614 },
1615 },
1616 "unknown key: .services.sv2.unknown_key",
1617 ValidationSettings(False),
1618 ),
1619 VaultTestConfig(
1620 {
1621 "global": {"key": "...", "unicode_normalization_form": "NFC"},
1622 "services": {
1623 "sv1": {"phrase": "abc", "length": 10, "upper": 1},
1624 "sv2": {
1625 "length": 10,
1626 "repeat": 1,
1627 "lower": 1,
1628 "unknown_key": True,
1629 },
1630 },
1631 },
1632 "",
1633 ValidationSettings(True),
1634 ),
1635 VaultTestConfig(
1636 {
1637 "global": {"key": "...", "unicode_normalization_form": "NFC"},
1638 "services": {
1639 "sv1": {"phrase": "abc", "length": 10, "upper": 1},
1640 "sv2": {
1641 "length": 10,
1642 "repeat": 1,
1643 "lower": 1,
1644 "unknown_key": True,
1645 },
1646 },
1647 },
1648 "",
1649 ValidationSettings(True),
1650 ),
1651 VaultTestConfig(
1652 {
1653 "global": {"key": "...", "unicode_normalization_form": "NFC"},
1654 "services": {
1655 "sv1": {"phrase": "abc", "length": 10, "upper": 1},
1656 "sv2": {
1657 "length": 10,
1658 "repeat": 1,
1659 "lower": 1,
1660 "unknown_key": True,
1661 },
1662 },
1663 },
1664 "",
1665 ValidationSettings(True),
1666 ),
1667]
1668"""The master list of test configurations for vault."""
1671# Common vault sample settings, passphrases, results, etc.
1672# --------------------------------------------------------
1675DUMMY_SERVICE = "service1"
1676"""A standard/sample service name."""
1677DUMMY_PASSPHRASE = "my secret passphrase"
1678"""A standard/sample passphrase."""
1679DUMMY_KEY1 = SUPPORTED_KEYS["ed25519"].public_key_data
1680"""A sample universally supported SSH test key (in wire format)."""
1681DUMMY_KEY1_B64 = bytes.decode(base64.standard_b64encode(DUMMY_KEY1), "ASCII")
1682"""
1683A sample universally supported SSH test key (in `authorized_keys` format).
1684"""
1685DUMMY_KEY2 = SUPPORTED_KEYS["rsa"].public_key_data
1686"""A second supported SSH test key (in wire format)."""
1687DUMMY_KEY2_B64 = bytes.decode(base64.standard_b64encode(DUMMY_KEY2), "ASCII")
1688"""A second supported SSH test key (in `authorized_keys` format)."""
1689DUMMY_KEY3 = SUPPORTED_KEYS["ed448"].public_key_data
1690"""A third supported SSH test key (in wire format)."""
1691DUMMY_KEY3_B64 = bytes.decode(base64.standard_b64encode(DUMMY_KEY3), "ASCII")
1692"""A third supported SSH test key (in `authorized_keys` format)."""
1693DUMMY_CONFIG_SETTINGS_AS_CONSTRUCTOR_ARGS = cast(
1694 "_types.VaultConstructorArgs",
1695 {
1696 "length": 10,
1697 "upper": 1,
1698 "lower": 1,
1699 "repeat": 5,
1700 "number": 1,
1701 "space": 1,
1702 "dash": 1,
1703 "symbol": 1,
1704 },
1705)
1706"""Sample vault settings, as constructor args."""
1707DUMMY_CONFIG_SETTINGS = cast(
1708 "_types.VaultConfigServicesSettings",
1709 DUMMY_CONFIG_SETTINGS_AS_CONSTRUCTOR_ARGS,
1710)
1711"""Sample vault settings."""
1712DUMMY_RESULT_PASSPHRASE = b".2V_QJkd o"
1713"""
1714The passphrase derived from [`DUMMY_SERVICE`][] using [`DUMMY_PASSPHRASE`][].
1715"""
1716DUMMY_RESULT_KEY1 = b"E<b<{ -7iG"
1717"""
1718The passphrase derived from [`DUMMY_SERVICE`][] using [`DUMMY_KEY1`][].
1719"""
1720DUMMY_PHRASE_FROM_KEY1_RAW = (
1721 b"\x00\x00\x00\x0bssh-ed25519"
1722 b"\x00\x00\x00@\xf0\x98\x19\x80l\x1a\x97\xd5&\x03n"
1723 b"\xcc\xe3e\x8f\x86f\x07\x13\x19\x13\t!33\xf9\xe46S"
1724 b"\x1d\xaf\xfd\r\x08\x1f\xec\xf8s\x9b\x8c_U9\x16|ST,"
1725 b"\x1eR\xbb0\xed\x7f\x89\xe2/iQU\xd8\x9e\xa6\x02"
1726)
1727"""
1728The "equivalent master passphrase" derived from [`DUMMY_KEY1`][] (raw format).
1729"""
1730DUMMY_PHRASE_FROM_KEY1 = b"8JgZgGwal9UmA27M42WPhmYHExkTCSEzM/nkNlMdr/0NCB/s+HObjF9VORZ8U1QsHlK7MO1/ieIvaVFV2J6mAg=="
1731"""
1732The "equivalent master passphrase" derived from [`DUMMY_KEY1`][] (in base64).
1733"""
1736# Vault native configuration storage data
1737# ---------------------------------------
1740VAULT_MASTER_KEY = "vault key"
1741"""
1742The storage passphrase used to encrypt all sample vault native configurations.
1743"""
1744VAULT_V02_CONFIG = "P7xeh5y4jmjpJ2pFq4KUcTVoaE9ZOEkwWmpVTURSSWQxbGt6emN4aFE4eFM3anVPbDRNTGpOLzY3eDF5aE1YTm5LNWh5Q1BwWTMwM3M5S083MWRWRFlmOXNqSFJNcStGMWFOS3c2emhiOUNNenZYTmNNMnZxaUErdlRoOGF2ZHdGT1ZLNTNLOVJQcU9jWmJrR3g5N09VcVBRZ0ZnSFNUQy9HdFVWWnFteVhRVkY3MHNBdnF2ZWFEbFBseWRGelE1c3BFTnVUckRQdWJSL29wNjFxd2Y2ZVpob3VyVzRod3FKTElTenJ1WTZacTJFOFBtK3BnVzh0QWVxcWtyWFdXOXYyenNQeFNZbWt1MDU2Vm1kVGtISWIxWTBpcWRFbyswUVJudVVhZkVlNVpGWDA4WUQ2Q2JTWW81SnlhQ2Zxa3cxNmZoQjJES0Uyd29rNXpSck5iWVBrVmEwOXFya1NpMi9saU5LL3F0M3N3MjZKekNCem9ER2svWkZ0SUJLdmlHRno0VlQzQ3pqZTBWcTM3YmRiNmJjTkhqUHZoQ0NxMW1ldW1XOFVVK3pQMEtUMkRMVGNvNHFlOG40ck5KcGhsYXg1b1VzZ1NYU1B2T3RXdEkwYzg4NWE3YWUzOWI1MDI0MThhMWZjODQ3MDA2OTJmNDQ0MDkxNGFiNmRlMGQ2YjZiNjI5NGMwN2IwMmI4MGZi"
1745"""
1746A sample vault native configuration, in v0.2 format, encoded in base64
1747and encrypted with [`VAULT_MASTER_KEY`][].
1748"""
1749VAULT_V02_CONFIG_DATA = {
1750 "global": {
1751 "phrase": str.rstrip(DUMMY_PASSPHRASE, "\n"),
1752 },
1753 "services": {
1754 "(meta)": {
1755 "notes": "This config was originally in v0.2 format.",
1756 },
1757 DUMMY_SERVICE: copy.copy(DUMMY_CONFIG_SETTINGS),
1758 },
1759}
1760"""
1761The plaintext contents (a vault native configuration) stored in
1762[`VAULT_V02_CONFIG`][].
1763"""
1764VAULT_V03_CONFIG = "sBPBrr8BFHPxSJkV/A53zk9zwDQHFxLe6UIusCVvzFQre103pcj5xxmE11lMTA0U2QTYjkhRXKkH5WegSmYpAnzReuRsYZlWWp6N4kkubf+twZ9C3EeggPm7as2Af4TICHVbX4uXpIHeQJf9y1OtqrO+SRBrgPBzgItoxsIxebxVKgyvh1CZQOSkn7BIzt9xKhDng3ubS4hQ91fB0QCumlldTbUl8tj4Xs5JbvsSlUMxRlVzZ0OgAOrSsoWELXmsp6zXFa9K6wIuZa4wQuMLQFHiA64JO1CR3I+rviWCeMlbTOuJNx6vMB5zotKJqA2hIUpN467TQ9vI4g/QTo40m5LT2EQKbIdTvBQAzcV4lOcpr5Lqt4LHED5mKvm/4YfpuuT3I3XCdWfdG5SB7ciiB4Go+xQdddy3zZMiwm1fEwIB8XjFf2cxoJdccLQ2yxf+9diedBP04EsMHrvxKDhQ7/vHl7xF2MMFTDKl3WFd23vvcjpR1JgNAKYprG/e1p/7"
1765"""
1766A sample vault native configuration, in v0.3 format, encoded in base64
1767and encrypted with [`VAULT_MASTER_KEY`][].
1768"""
1769VAULT_V03_CONFIG_DATA = {
1770 "global": {
1771 "phrase": str.rstrip(DUMMY_PASSPHRASE, "\n"),
1772 },
1773 "services": {
1774 "(meta)": {
1775 "notes": "This config was originally in v0.3 format.",
1776 },
1777 DUMMY_SERVICE: copy.copy(DUMMY_CONFIG_SETTINGS),
1778 },
1779}
1780"""
1781The plaintext contents (a vault native configuration) stored in
1782[`VAULT_V03_CONFIG`][].
1783"""
1784VAULT_STOREROOM_CONFIG_ZIPPED = b"""
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
1815dnAibw1brWVXM++8iYcUg84TMbJXntFYCyrNw1NF+008I02PeH4C8oDID6fIoKvsw3p7WJJ/I9Yp
1816a6oJzlJiP5JGxRxZPj50N6EMtzNB+tZoIGxgtOFVpiJ05yMQFztY6I6LKIgvXW/s919GIjGshqdM
1817XVPFxaKG4p9Iux/xazf48FY8O7SMmbQC1VsXIYo+7eSpIY67VzrCoh41wXPklOWS6CV8RR/JBSqq
18188lHkcz8L21lMCOrVR1Cs0ls4HLIhUkqr9YegTJ67VM7xevUsgOI7BkPDldiulRgX+sdPheCyCacu
1819e7/b/nk0SXWF7ZBxsR1awYqwkFKz41/1bZDsETsmd8n1DHycGIvRULv3yYhKcvWQ4asAMhP1ks5k
1820AgOcrM+JFvpYA86Ja8HCqCg8LihEI1e7+m8F71Lpavv/UEsDBBQAAAAIAJ1WGVnKO2Ji+AEAAGsC
1821AAACAAAAMWENx7dyo0AAANDen+GWAonMzbggLsJakgGBOhBLlGBZsjz373eve7+fKyJTM/Sff85/
1822P5QMwMFfAWipfXwvFPWU582cd3t7JVV5pBV0Y1clL4eKUd0w1m1M5JrkgW5PlfpOVedgABSe4zPY
1823LnSIZVuen5Eua9QY8lQ7rxW7YIqeajhgLfL54BIcY90fd8ANixlcM8V23Z03U35Txba0BbSguc0f
1824NRF83cWp+7rOYgNO9wWLs915oQmWAqAtqRYCiWlgAtxYFg0MnNS4/G80FvFmQTh0cjwcF1xEVPeW
1825l72ky84PEA0QMgRtQW+HXWtE0/vQTtNKzvNqPfrGZCldL5nk9PWhhPEQ/azyW11bz2eB+aM0g0r7
18260/5YkO9er10YonsBT1rEn0lfBXDHwtwbxG2bdqELTuEtX2+OEih7K43rN2EvpXX47azaNpe/drIz
1827wgAdhpfZ/mZwaGFX0c7r5HCTnroNRi5Bx/vu7m1A7Nt1dix4Gl/aPLCWQzpwmdIMJDiqD1RGpc5v
1828+pDLrpfhZOVhLjAPSQ0V7mm/XNSca8oIsDjwdvR438RQCU56mrlypklS4/tJAe0JZNZIgBmJszjG
1829AFbsmNYTJ9GmULB9lXmTWmrME592S285iWU5SsJcE1s+3oQw9QrvWB+e3bGAd9e+VFmFqr6+/gFQ
1830SwECHgMUAAAACACdVhlZ01RRk9IAAADmAAAABQAAAAAAAAABAAAApIEAAAAALmtleXNQSwECHgMU
1831AAAACACdVhlZ3Wlf4QUDAADUAwAAAgAAAAAAAAABAAAApIH1AAAAMDBQSwECHgMUAAAACACdVhlZ
1832/aaiwcoBAAArAgAAAgAAAAAAAAABAAAApIEaBAAAMDNQSwECHgMUAAAACACdVhlZs14oCcgBAAAr
1833AgAAAgAAAAAAAAABAAAApIEEBgAAMDlQSwECHgMUAAAACACdVhlZyjtiYvgBAABrAgAAAgAAAAAA
1834AAABAAAApIHsBwAAMWFQSwUGAAAAAAUABQDzAAAABAoAAAAA
1835"""
1836"""
1837A sample vault native configuration, in storeroom format, encrypted with
1838[`VAULT_MASTER_KEY`][]. The configuration is compressed (zip archive)
1839and then encoded in base64.
1840"""
1841VAULT_STOREROOM_CONFIG_DATA = {
1842 "global": {
1843 "phrase": str.rstrip(DUMMY_PASSPHRASE, "\n"),
1844 },
1845 "services": {
1846 "(meta)": {
1847 "notes": "This config was originally in storeroom format.",
1848 },
1849 DUMMY_SERVICE: copy.copy(DUMMY_CONFIG_SETTINGS),
1850 },
1851}
1852"""
1853The parsed vault configuration stored in
1854[`VAULT_STOREROOM_CONFIG_ZIPPED`][].
1855"""
1857VAULT_STOREROOM_BROKEN_DIR_CONFIG_ZIPPED_JAVASCRIPT_SOURCE = """
1858// Executed in the top-level directory of the vault project code, in Node.js.
1859const storeroom = require('storeroom')
1860const Store = require('./lib/store.js')
1861let store = new Store(storeroom.createFileAdapter('./broken-dir'), 'vault key')
1862await store._storeroom.put('/services/array/', ['entry1','entry2'])
1863// The resulting "broken-dir" was then zipped manually.
1864"""
1865"""
1866The JavaScript source for the script that generated the storeroom
1867archive in [`VAULT_STOREROOM_BROKEN_DIR_CONFIG_ZIPPED`][].
1868"""
1869VAULT_STOREROOM_BROKEN_DIR_CONFIG_ZIPPED = b"""
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
1904"""
1905"""
1906A sample corrupted storeroom archive, encrypted with
1907[`VAULT_MASTER_KEY`][]. The configuration is compressed (zip archive)
1908and then encoded in base64.
1910The archive contains a directory `/services/array/` that claims to have
1911two child items 'entry1' and 'entry2', but no such child items are
1912present in the archive. See
1913[`VAULT_STOREROOM_BROKEN_DIR_CONFIG_ZIPPED_JAVASCRIPT_SOURCE`][] for
1914the exact script that created this archive.
1915"""
1917VAULT_STOREROOM_BROKEN_DIR_CONFIG_ZIPPED2_JAVASCRIPT_SOURCE = """
1918// Executed in the top-level directory of the vault project code, in Node.js.
1919const storeroom = require('storeroom')
1920const Store = require('./lib/store.js')
1921let store = new Store(storeroom.createFileAdapter('./broken-dir'), 'vault key')
1922await store._storeroom.put('/services/array/', 'not a directory index')
1923// The resulting "broken-dir" was then zipped manually.
1924"""
1925"""
1926The JavaScript source for the script that generated the storeroom
1927archive in [`VAULT_STOREROOM_BROKEN_DIR_CONFIG_ZIPPED2`][].
1928"""
1929VAULT_STOREROOM_BROKEN_DIR_CONFIG_ZIPPED2 = b"""
1930UEsDBAoAAAAAAM6NSVmrcHdV5gAAAOYAAAAFAAAALmtleXN7InZlcnNpb24iOjF9CkV3ZS9LZkJp
1931L0V0OUcrZmxYM3gxaFU4ZjE4YlE3S253bHoxN0IxSDE3cUhVOGdWK2RpWWY5MTdFZ0YrSStidEpZ
1932VXBzWVZVck45OC9uLzdsZnl2NUdGVEg2NWZxVy93YjlOc2MxeEZ4ck43Q3p4eTZ5MVAxZzFPb2VK
1933b0RZU3J6YXlwT0E2M3pidmk0ZTRiREMyNXhPTXl5NHBoMDFGeGdnQmpSNnpUcmR2UDk2UlZQd0I5
1934WitOZkZWZUlXT1NQN254ZFNYMGdFbkZ4SDBmWDkzNTFaTTZnPVBLAwQKAAAAAADOjUlZJg3/BhcC
1935AAAXAgAAAgAAADBieyJ2ZXJzaW9uIjoxfQpBVXJJMjNDQ2VpcW14cUZRMlV4SUpBaUoxNEtyUzh2
1936SXpIa2xROURBaFRlVHNFMmxPVUg4WUhTcUk1cXRGSHBqY3c1WkRkZmRtUlEwQXVGRjllY3lkam14
1937dDdUemRYLzNmNFUvTGlVV2dLRmQ1K1FEN3BlVlE1bWpqeHNlUEpHTDlhTWlKaGxSUVB4SmtUbjBx
1938U2poM1RUT0ZZbVAzV0JkdlUyWnF2RzhaSDk2cU1WcnZsQ0dMRmZTc2svVXlvcHZKdENONUVXcTRZ
1939SDUwNFNiejFIUVhWd2RjejlrS1BuR3J6SVA4ZmZtZnhXQ0U0TmtLb0ZPQXZuNkZvS3FZdGlGbFE9
1940PQpBVXBMUVMrMG9VeEZTeCtxbTB3SUtyM1MvTVJxYWJJTFlEUnY0aHlBMVE2TGR2Nlk0UmJ0enVz
1941NzRBc0cxbVhhenlRU2hlZVowdk0xM2ZyTFA4YlV0VHBaRyszNXF1eUhLM2NaWVJRZUxKM0JzejZz
1942b0xaQjNZTkpNenFxTTQrdzM1U0FZZ2lMU1NkN05NeWVrTHNhRUIzRDFOajlTRk85K3NGNEpFMWVL
1943UXpNMkltNk9qOUNVQjZUSTV3UitibksxN1BnY2RaeTZUMVRMWElVREVxcDg4dWdsWmRFTVcrNU9k
1944aE5ZbXEzZERWVWV4UnJpM1AwUmVBSi9KMGdJNkNoUUE9PVBLAwQKAAAAAADOjUlZTNfdphcCAAAX
1945AgAAAgAAADBmeyJ2ZXJzaW9uIjoxfQpBWVJqOVpIUktGUEVKOHM2YVY2TkRoTk5jQlZ5cGVYUmdz
1946cnBldFQ0cGhJRGROWFdGYzRia0daYkJxMngwRDFkcVNjYWk5UzEveDZ2K28zRE0rVEF2OVE3ZFVR
1947QWVKR3RmRkhJZDZxWW0ybEdNSnF5WTRNWm14aE9YdXliend0V3Q4Mnhvb041QTZNcWpINmxKQllD
1948UUN3ZEJjb3RER0EwRnlnVTEzeHV2WnIzT1puZnFFRGRqbzMxNkw5aExDN1RxMTYwUHpBOXJOSDMz
1949ZkNBcUhIVXZiYlFQQWErekw1d3dEN3FlWkY2MHdJaEwvRmk5L3JhNGJDcHZRNC9ORWpRd3c9PQpB
1950WWNGUDB1Y2xMMHh3ZDM2UXZXbm4wWXFsOU5WV0s3c05CMTdjdmM3N3VDZ0J2OE9XYkR5UHk5d05h
1951R2NQQzdzcVdZdHpZRlBHR0taVjhVUzA1YTVsV1BabDNGVFNuQXNtekxPelBlcFZxaitleDU3aEsx
1952QnV1bHkrUCtYQkE0YUtsaDM3c0RJL3I0UE1BVlJuMDNoSDJ5dEhDMW9PbjF0V1M5Q1NLV1pSMThh
1953djdTT0RBMVBNRnFYTmZKZVNTaVJiQ2htbDdOcFVLbjlXSGJZandybDlqN0JSdy9kWjhNQldCb3Ns
1954Nlc1dGZtdnJMVHhGRFBXYUgzSUp0T0czMEI1M3c9PVBLAwQKAAAAAADOjUlZn9rNID8CAAA/AgAA
1955AgAAADFkeyJ2ZXJzaW9uIjoxfQpBYWFBb3lqaGljVDZ4eXh1c0U0RVlDZCtxbE81Z0dEYTBNSFVS
1956MmgrSW9QMHV4UkY3b1BRS2czOHlQUEN3Ny9MYVJLQ0dQZ0RyZ2RpTWJTeUwzZ3ZNMFhseVpVMVBW
1957QVJvNEFETU9lbXgrOWhtS0hjQWNKMG5EeW5oSkhGYTYyb2xyQUNxekZzblhKNVBSeEVTVzVEbUh0
1958Ui9nRm5Wa1FvalhyVW4ybmpYMjVVanZQaXhlMU96Y0daMmQ0MjdVTGdnY1hqMkhSdjJiZldDNDUw
1959SGFXS3FDckZlYWlrQ2xkUUM2WGV3SkxZUjdvQUY3UjVha2ttK3M2MXNCRTVCaTg0QmJLWHluc1NG
1960ejE0TXFrd2JMK1VMYVk9CkFUT3dqTUFpa3Q4My9NTW5KRXQ2b3EyNFN4KzJKNDc2K2gyTmEzbHUr
1961MDg0cjlBT25aaUk0TmlYV0N1Q0lzakEzcTBwUHFJS1VXZHlPQW9uM2VHY0huZUppWUtVYllBaUJI
1962MVNmbnhQQkMzZkFMRklybkQ4Y0VqeGpPcUFUaTQ5dE1mRmtib0dNQ3dEdFY0V3NJL0tLUlRCOFd1
1963MnNXK2J0V3QzVWlvZG9ZeUVLTDk3ekNNemZqdGptejF4SDhHTXY5WDVnaG9NSW5RQVNvYlRreVZ4
1964dWo5YnlDazdNbU0vK21ZL3AwZE9oYVY0Nncwcm04UGlvWEtzdzR4bXB3ditDWC9PRXV3Uy9meDJT
1965Y0lOQnNuYVRiWT1QSwECHgMKAAAAAADOjUlZq3B3VeYAAADmAAAABQAAAAAAAAAAAAAApIEAAAAA
1966LmtleXNQSwECHgMKAAAAAADOjUlZJg3/BhcCAAAXAgAAAgAAAAAAAAAAAAAApIEJAQAAMGJQSwEC
1967HgMKAAAAAADOjUlZTNfdphcCAAAXAgAAAgAAAAAAAAAAAAAApIFAAwAAMGZQSwECHgMKAAAAAADO
1968jUlZn9rNID8CAAA/AgAAAgAAAAAAAAAAAAAApIF3BQAAMWRQSwUGAAAAAAQABADDAAAA1gcAAAAA
1969"""
1970"""
1971A sample corrupted storeroom archive, encrypted with
1972[`VAULT_MASTER_KEY`][]. The configuration is compressed (zip archive)
1973and then encoded in base64.
1975The archive contains a directory `/services/array/` whose list of child
1976items does not adhere to the serialization format. See
1977[`VAULT_STOREROOM_BROKEN_DIR_CONFIG_ZIPPED2_JAVASCRIPT_SOURCE`][] for
1978the exact script that created this archive.
1979"""
1981VAULT_STOREROOM_BROKEN_DIR_CONFIG_ZIPPED3_JAVASCRIPT_SOURCE = """
1982// Executed in the top-level directory of the vault project code, in Node.js.
1983const storeroom = require('storeroom')
1984const Store = require('./lib/store.js')
1985let store = new Store(storeroom.createFileAdapter('./broken-dir'), 'vault key')
1986await store._storeroom.put('/services/array/', [null, 1, true, [], {}])
1987// The resulting "broken-dir" was then zipped manually.
1988"""
1989"""
1990The JavaScript source for the script that generated the storeroom
1991archive in [`VAULT_STOREROOM_BROKEN_DIR_CONFIG_ZIPPED3`][].
1992"""
1993VAULT_STOREROOM_BROKEN_DIR_CONFIG_ZIPPED3 = b"""
1994UEsDBAoAAAAAAEOPSVnVlcff5gAAAOYAAAAFAAAALmtleXN7InZlcnNpb24iOjF9CkV4dVBHUDBi
1995YkxrUVdvWnV5ZUJQRy8xdmM2MCt6MThOa3BsS09ydFAvUTVnQmxkYVpIOG10dTE5VWZFNGdGRGRj
1996eHJtWUd4eXZDZFNqcVlOaDh4cTlzM3VydkdRTWFwcnhtdlZGZUxoSW4zZnVlTDAweEk0ZmlLenZN
1997MmthUlRsNWNORGh3eUNlWVk4dzhBcXNhYjNyVWVsOEE0eVQ0cHU2d2tmQ3dTWUdqeG5HR29EcWJK
1998VnVJVWNpZVBEcU9PTzU2b0MyMG9lT01adFVkTUtxV28zYnFZPVBLAwQKAAAAAABDj0lZ77OVHxcC
1999AAAXAgAAAgAAADBjeyJ2ZXJzaW9uIjoxfQpBZllFQVVobEkyU2lZeGlrdWh0RzRNbUN3L1V2THBN
2000VVhwVlB0NlRwdzRyNGdocVJhbGZWZ0hxUHFtbTczSnltdFFrNnZnR2JRdUpiQmVlYjYwOHNrMGk4
2001ZFJVZjNwdlc2SnUyejljQkdwOG5mTFpTdlNad1lLN09UK2gzSDNDcmoxbXNicEZUcHVldW81NXc1
2002dGdYMnBuWXNWTVcrczdjaHEyMUIya2lIVEZrdGt1MXlaRzhPYkVUQjNCOFNGODVVbi9CUjFEMHJ1
2003ME9zOWl4ZWM2VmNTMitTZndtNnNtSlk2ZW9ZNTJzOGJNRGdYMndjQ0srREdkOEo2VWp0NG5OQVE9
2004PQpBUWlPRnRZcmJybWUycEwxRFpGT1BjU0RHOUN2cVkvbHhTWGIwaVJUdmtIWFc2bEtHL0p4RUtU
2005d3RTc0RTeDhsMTUvaHRmbWpOQ2tuTzhLVEFoKzhRQm5FbjZ0a2x5Y3BmeEIrTUxLRjFCM1Q1bjcv
2006T0VUMExMdmgxU2k1bnRRNXhTUHZZNWtXeUMyZjhXUXFZb3FSNU5JVENMeDV6dWNsQ3dGb2kvVXc4
2007OWNNWjM1MHBSbThzUktJbjJFeDUrQ1JwS3ZHdnBHbFJaTmk5VHZmVkNic1FCalR3MC9aeklTdzVQ
2008NW9BVWE2U1ExUVFnNHg4VUNkY0s2QUNLaFluY0d4TVE9PVBLAwQKAAAAAABDj0lZGk9LVj8CAAA/
2009AgAAAgAAADE0eyJ2ZXJzaW9uIjoxfQpBY1g2NVpMUWk4ck9pUlIyWGEwQlFHQVhQVWF2aHNJVGVY
2010c2dzRk9OUmFTRzJCQlg0SGxJRHpwRUd5aDUrZ2czZVRwWDFNOERua3pMeTVzcWRkMFpmK3padTgz
2011Qm52Y1JPREVIVDllUW91YUtPTWltdlRYanNuSXAxUHo5VGY1TlRkRjNJVTd2V1lhUDg4WTI5NG1i
2012c1VVL2RKVTZqZ3ZDbUw2cE1VZ28xUU12bGJnaVp3cDV1RDFQZXlrSXdKVWdJSEgxTEpnYi9xU2tW
2013c25leW1XY1RXR0NobzRvZGx3S2hJWmFCelhvNFhlN2U1V2I2VHA3Rkk5VUpVcmZIRTAvcVdrZUZE
2014VmxlazY3cUx3ZFZXcU9DdFk9CkFhSGR0QjhydmQ0U3N4ZmJ5eU1OOHIzZEoxeHA5NmFIRTQvalNi
2015Z05hZWttaDkyb2ROM1F4MUlqYXZsYVkxeEt1eFF3KzlwTHFIcTF5a1JSRjQzL2RVWGFIRk5UU0NX
2016OVFsdmd3KzMwa1ZhSEdXRllvbFRnRWE4djQ3b3VrbGlmc01PZGM0YVNKb2R4ZUFJcVc3Q1cwdDVR
2017b2RUbWREUXpqc3phZkQ4R2VOd2NFQjdGMHI2RzNoZEJlQndxd3Z6eENVYnpSUmU5bEQ3NjQ3RFp1
2018bEo1U3c4amlvV0paTW40NlZhV3BYUXk4UnNva3hHaW00WUpybUZIQ2JkVU9qSWJsUmQ1Z3VhUDNU
2019M0NxeHRPdC94b1BhOD1QSwMECgAAAAAAQ49JWVJM8QYXAgAAFwIAAAIAAAAxNnsidmVyc2lvbiI6
2020MX0KQVlCWDF6M21qUlQrand4M2FyNkFpemxnalJZbUM0ZHg5NkxVQVBTVHNMWXJKVHFtWnd5N0Jy
2021OFlCcElVamorMHdlT3lNaUtLVnFwaER3RXExNWFqUmlSZUVEQURTVHZwWmlLZUlnZjR5elUzZXNP
2022eDJ2U2J1bXhTK0swUGZVa2tsSy9TRmRiU3EvUHFMRjBDRTVCMXNyKzJLYTB2WlJmak94R3VFeFRD
2023RXozN0ZlWDNNR3NCNkhZVHEzaUJWcUR6NVB6eHpCWWM5Kyt6RitLS1RnMVp2NGRtRmVQTC9JSEY5
2024WnV6TWlqRXdCRkE3WnJ0dkRqd3ZYcWtsMVpsR0c4eUV3PT0KQVhUWkRLVnNleldpR1RMUVZqa2hX
2025bXBnK05MYlM0M2MxZEpvK2xGcC9yWUJYZkw3Wll5cGdjWE5IWXNzd01nc2VSSTAzNmt6bGZkdGNa
2026bTdiUUN6M2JuQmZ6ZlorZFFuT2Y5STVSU2l0QzB2UmsydkQrOFdwbmRPSzNucGY5S0VpWklOSzVq
2027TEZGTTJDTkNmQzBabXNRUlF3T0k2N3l5ZHhjVnFDMXBnWHV6QXRXamlsSUpnN0p6eUtsY3BJUGJu
2028SUc0UzRSUlhIdW1wZnpoeWFZWkd6T0FDamRSYTZIMWJxYkJkZXFaSHMvQXJvM25mVjdlbjhxSUE5
2029aVUrbnNweXFnPT1QSwECHgMKAAAAAABDj0lZ1ZXH3+YAAADmAAAABQAAAAAAAAAAAAAApIEAAAAA
2030LmtleXNQSwECHgMKAAAAAABDj0lZ77OVHxcCAAAXAgAAAgAAAAAAAAAAAAAApIEJAQAAMGNQSwEC
2031HgMKAAAAAABDj0lZGk9LVj8CAAA/AgAAAgAAAAAAAAAAAAAApIFAAwAAMTRQSwECHgMKAAAAAABD
2032j0lZUkzxBhcCAAAXAgAAAgAAAAAAAAAAAAAApIGfBQAAMTZQSwUGAAAAAAQABADDAAAA1gcAAAAA
2033"""
2034"""
2035A sample corrupted storeroom archive, encrypted with
2036[`VAULT_MASTER_KEY`][]. The configuration is compressed (zip archive)
2037and then encoded in base64.
2039The archive contains a directory `/services/array/` whose list of child
2040items are not all valid item names. See
2041[`VAULT_STOREROOM_BROKEN_DIR_CONFIG_ZIPPED3_JAVASCRIPT_SOURCE`][] for
2042the exact script that created this archive.
2043"""
2045VAULT_STOREROOM_BROKEN_DIR_CONFIG_ZIPPED4_JAVASCRIPT_SOURCE = """
2046// Executed in the top-level directory of the vault project code, in Node.js.
2047const storeroom = require('storeroom')
2048const Store = require('./lib/store.js')
2049let store = new Store(storeroom.createFileAdapter('./broken-dir'), 'vault key')
2050await store._storeroom.put('/dir/subdir/', [])
2051await store._storeroom.put('/dir/', [])
2052// The resulting "broken-dir" was then zipped manually.
2053"""
2054"""
2055The JavaScript source for the script that generated the storeroom
2056archive in [`VAULT_STOREROOM_BROKEN_DIR_CONFIG_ZIPPED4`][].
2057"""
2058VAULT_STOREROOM_BROKEN_DIR_CONFIG_ZIPPED4 = b"""
2059UEsDBAoAAAAAAE+5SVloORS+5gAAAOYAAAAFAAAALmtleXN7InZlcnNpb24iOjF9CkV6dWRoNkRQ
2060YTlNSWFabHZ5TytVYTFuamhjV2hIaTFBU0lKYW5zcXBxVlA0blN2V0twUzdZOUc2bjFSbi8vUnVM
2061VitwcHp5SC9RQk83R0hFenNVMzdCUzFwUmVVeGhxUVlVTE56OXZvQ0crM1ZaL3VncU44dDJiU05m
2062Nyt5K3hiNng2aVlFUmNZYTJ0UkhzZVdIc0laTE9ha2lDb0lRVGV3cndwYjVMM2pnd0E3SXBzaDkz
2063QkxHSzM5dXNYNmo0R0I2WkRUeW5JcGk4V3JkbDhnWVZCN0tVPVBLAwQKAAAAAABPuUlZ663uUhcC
2064AAAXAgAAAgAAADAzeyJ2ZXJzaW9uIjoxfQpBV2wzS2gzd21ZSFVZZU1RR3BLSVowdVd1VXFna09h
2065YmRjNzNYYXVsZTNtVS9sN2Zvd1AyS21jbFp3ZDM5V3lYVzRTcEw4R0l4YStDZW51S3V0Wm5nb0FR
2066bWlnaUJUbkFaais5TENCcGNIWlZNY2RBVkgxKzBFNGpsanZ1UkVwZ0tPS05LZjRsTUl1QnZ4VmFB
2067ZkdwNHJYNEZ4MmpPSlk1Y3NQZzBBRFBoZVAwN29GWVQ3alorSUNEK1AxNGZPdWpwMGRUeDRrTDIy
2068LzlqalRDNXBCNVF5NW5iOUx3Zk5DUWViSUVpaTZpbU0vRmFrK1dtV05tMndqMERSTEc4RHY3ZkE9
2069PQpBU0c3NTNGTVVwWmxjK3E1YXRzcC93OUNqN2JPOFlpY24wZHg2UGloTmwzUS9WSjVVeGJmU3l0
2070ZDFDNDBRU2xXeTJqOTJDWUd3VER6eEdBMXVnb0FCYi9kTllTelVwbHJFb3BuUVphYXdsdTVwV2x0
2071Y1E5WTcveWN4S2E4b0JaaGY3RkFYcGo2c01wUW9zNzI5VFVabFd4UmI4VFRtN2FrVnR1OXcvYXlK
2072RS9reDh4ZUYxSGJlc3Q4N1IxTGg2ODd3dS9XVUN2ZjNXYXo1VjNnZWY0RnpUTXg0bkpqSlZOd0U0
2073SzAxUTlaVzQ0bmVvbExPUVI1MkZDeDZvbml3RW9tenc9PVBLAwQKAAAAAABPuUlZRXky4CsCAAAr
2074AgAAAgAAADEweyJ2ZXJzaW9uIjoxfQpBWmlYWVlvNUdCY2d5dkFRaGtyK2ZjUkdVSkdabDd2dE5w
2075T2Mrd1VzbXJhQWhRN3dKdlYraGhKcTlrcWNKQnBWU0gyUTBTTVVhb29iNjBJM1NYNUNtTkJRU2FH
2076M3prd0Y0T2F4TnpCZUh0NFlpaDd4Y3p2ak4xR0hISDJQYW0xam05K09ja3JLVmNMVURtNXRKb2ZC
2077Z1E4Q2NwMGZMVkdEaURjNWF0MjVMc2piQVcvNkZFSnJ5VVBHWis4UVdYRmlWMGdtVVZybVc3VUFy
2078dGhJQitWNTdZS1BORi95Nng2OU43UTFQbmp1cUczdlpybzljMEJ3d012NWoyc3BMMTJHcTdzTDZE
2079alB1d0dHbnB2MkVZQTFLbmc9CkFTdjQwUkgzRmxzbGVlU1NjRlZNRmh3dEx6eEYxK2xpcmxEL29X
2080alJLQ05qVWZhUVpJTWpqMWRoVkhOakNUTWhWZ1ZONkl3b04xTnFOMEV6cmdhaTFBWnNiMm9UczYw
2081QkI1UGh0U0hhQ2U2WllUeE1JemFPS2FIK0w2eHhtaXIrTlQxNTRXS0x5amJMams3MU1na3Nwa0Yy
2082WDBJMnlaWW5IUUM0bmdEL24yZzRtSVI2Q1hWL0JOUXNzeTBEeXdGLzN6eGRRYWw5cFBtVk1qYnFu
2083cHY5SFNqRTg4S25naVpBWFhJWU1OVGF2L3Q3Y3dEWGdNekhKTlU0Y2xnVUtIQVZ3QT09UEsDBAoA
2084AAAAAE+5SVkPfKx9FwIAABcCAAACAAAAMWR7InZlcnNpb24iOjF9CkFYbHNLRzQwZG5ibTJvcXdY
2085U2ZrSWp3Mmxpa0lDS3hVOXU3TU52VkZ1NEJ2R1FVVitSVVdsS3MxL25TSlBtM2U2OTRvVHdoeDFo
2086RFF3U0M5U0QvbXd5bnpjSTloUnRCUWVXMkVMOVU5L1ZGcHFsVWY3Z1ZOMHZ0ZWpXYnV4QnhsZlRD
2087Tys4SFBwU2Zaa2VOUld5R2JNdzBFSU9LTmxRYjk3OUF0c1g3THR0NytaTkJnakZHYkZxaHdwa3kx
2088WUNDVng1UmNZZ2tma2ZjWnVncGpzc1RzNVFvK1p3QXBEcDZ4V3JjSHMxUDhvNktBRzAwcjZZbkNM
2089N2ErU1dwZmVNTUJhZz09CkFadVF0cFZMWmVvb292NkdyQlpnb3B6VmRGUXBlK1h6QXZuZ2dPVnZM
2090VWtCYVF2akl5K1VLdXVUVlFoQ1JiMVp6dGZQL2dsNnoxOEsyZW5sQlo2bGJTZnoxTlBWeUVzYXB3
2091dDVpUVh4azd5UkJlZks1cFlsNTduUXlmcFZQbzlreFpnOVdHTkV3NVJ5MkExemhnNGl6TWxLRmJh
2092UjZFZ0FjQ3NFOXAveGRLa29ZNjhOUlZmNXJDM3lMQjc3ZWgyS1hCUld2WDNZcE9XdW00OGtsbmtI
2093akJjMFpiQmUrT3NZb3d5cXpoRFA2ZGQxRlFnMlFjK09vc3B4V0sycld4M01HZz09UEsBAh4DCgAA
2094AAAAT7lJWWg5FL7mAAAA5gAAAAUAAAAAAAAAAAAAAKSBAAAAAC5rZXlzUEsBAh4DCgAAAAAAT7lJ
2095Weut7lIXAgAAFwIAAAIAAAAAAAAAAAAAAKSBCQEAADAzUEsBAh4DCgAAAAAAT7lJWUV5MuArAgAA
2096KwIAAAIAAAAAAAAAAAAAAKSBQAMAADEwUEsBAh4DCgAAAAAAT7lJWQ98rH0XAgAAFwIAAAIAAAAA
2097AAAAAAAAAKSBiwUAADFkUEsFBgAAAAAEAAQAwwAAAMIHAAAAAA==
2098"""
2099"""
2100A sample corrupted storeroom archive, encrypted with
2101[`VAULT_MASTER_KEY`][]. The configuration is compressed (zip archive)
2102and then encoded in base64.
2104The archive contains two directories `/dir/` and `/dir/subdir/`, where
2105`/dir/subdir/` is a correctly serialized directory, but `/dir/` does not
2106contain `/dir/subdir/` in its list of child items. See
2107[`VAULT_STOREROOM_BROKEN_DIR_CONFIG_ZIPPED4_JAVASCRIPT_SOURCE`][] for
2108the exact script that created this archive.
2109"""
2111# Error messages
2112# ==============
2114CANNOT_LOAD_CRYPTOGRAPHY = (
2115 "Cannot load the required Python module 'cryptography'."
2116)
2117"""
2118The expected `derivepassphrase` error message when the `cryptography`
2119module cannot be loaded, which is needed e.g. by the `export vault`
2120subcommands.
2121"""