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

1# SPDX-FileCopyrightText: 2026 Marco Ricci <software@the13thletter.info> 

2# 

3# SPDX-License-Identifier: Zlib 

4 

5"""Testing data for `derivepassphrase`. 

6 

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. 

10 

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. 

17 

18""" 

19 

20from __future__ import annotations 

21 

22import base64 

23import copy 

24import ctypes 

25import enum 

26import errno 

27import os 

28import socket 

29from typing import TYPE_CHECKING, cast 

30 

31from typing_extensions import NamedTuple, assert_never 

32 

33from derivepassphrase import _types, ssh_agent, vault 

34from derivepassphrase.ssh_agent import socketprovider 

35 

36__all__ = () 

37 

38if TYPE_CHECKING: 

39 from collections.abc import Mapping 

40 from typing import NoReturn 

41 

42 import pytest 

43 from typing_extensions import Any 

44 

45 

46# Actions 

47# ======= 

48 

49 

50class ListKeysAction(str, enum.Enum): 

51 """Test fixture settings for [`ssh_agent.SSHAgentClient.list_keys`][]. 

52 

53 Attributes: 

54 EMPTY: Return an empty key list. 

55 FAIL: Raise an [`ssh_agent.SSHAgentFailedError`][]. 

56 FAIL_RUNTIME: Raise an [`ssh_agent.TrailingDataError`][]. 

57 

58 """ 

59 

60 EMPTY = enum.auto() 

61 """""" 

62 FAIL = enum.auto() 

63 """""" 

64 FAIL_RUNTIME = enum.auto() 

65 """""" 

66 

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() 

79 

80 

81class SignAction(str, enum.Enum): 

82 """Test fixture settings for [`ssh_agent.SSHAgentClient.sign`][]. 

83 

84 Attributes: 

85 FAIL: Raise an [`ssh_agent.SSHAgentFailedError`][]. 

86 FAIL_RUNTIME: Raise an [`ssh_agent.TrailingDataError`][]. 

87 

88 """ 

89 

90 FAIL = enum.auto() 

91 """""" 

92 FAIL_RUNTIME = enum.auto() 

93 """""" 

94 

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() 

105 

106 

107class SocketAddressAction(str, enum.Enum): 

108 """Test fixture settings for the SSH agent socket address. 

109 

110 Attributes: 

111 MANGLE_ADDRESS: 

112 Mangle the socket address. 

113 

114 For UNIX domain sockets, mangle the `SSH_AUTH_SOCK` 

115 environment variable. 

116 

117 For Windows named pipes, skip the test. (Addresses are 

118 fixed, so cannot be mangled.) 

119 UNSET_ADDRESS: 

120 Unset the socket address. 

121 

122 For UNIX domain sockets, unset the `SSH_AUTH_SOCK` 

123 environment variable. 

124 

125 For Windows named pipes, skip the test. (Adresses are 

126 fixed, so cannot be unset.) 

127 

128 """ 

129 

130 MANGLE_ADDRESS = enum.auto() 

131 """""" 

132 UNSET_ADDRESS = enum.auto() 

133 """""" 

134 

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

143 

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)) 

148 

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

168 

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 

173 

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() 

187 

188 

189class SystemSupportAction(str, enum.Enum): 

190 """Test fixture settings for [`ssh_agent.SSHAgentClient`][] system support. 

191 

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. 

204 

205 """ 

206 

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 """""" 

215 

216 def __call__( 

217 self, monkeypatch: pytest.MonkeyPatch, /, *_args: Any, **_kwargs: Any 

218 ) -> None: 

219 """Execute the respective action. 

220 

221 Args: 

222 monkeypatch: The current monkeypatch context. 

223 

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() 

258 

259 

260# Types 

261# ===== 

262 

263# SSH test keys and agent info 

264# ---------------------------- 

265 

266 

267class SSHTestKeyDeterministicSignatureClass(str, enum.Enum): 

268 """The class of a deterministic signature from an SSH test key. 

269 

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. 

282 

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. 

288 

289 [PUTTY_CVE_2024_31497]: https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/vuln-p521-bias.html 

290 

291 """ 

292 

293 SPEC = enum.auto() 

294 """""" 

295 RFC_6979 = enum.auto() 

296 """""" 

297 Pageant_068_080 = enum.auto() 

298 """""" 

299 

300 

301class SSHTestKeyDeterministicSignature(NamedTuple): 

302 """An SSH test key deterministic signature. 

303 

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]. 

314 

315 """ 

316 

317 signature: bytes 

318 """""" 

319 derived_passphrase: bytes 

320 """""" 

321 signature_class: SSHTestKeyDeterministicSignatureClass = ( 

322 SSHTestKeyDeterministicSignatureClass.SPEC 

323 ) 

324 """""" 

325 

326 

327class SSHTestKey(NamedTuple): 

328 """An SSH test key. 

329 

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. 

346 

347 """ 

348 

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 """""" 

361 

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. 

368 

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. 

374 

375 """ 

376 return vault.Vault.is_suitable_ssh_key( 1ai

377 self.public_key_data, client=client 

378 ) 

379 

380 

381class KnownSSHAgentType(str, enum.Enum): 

382 """Known SSH agent types. 

383 

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. 

401 

402 """ 

403 

404 UNKNOWN = "(unknown)" 

405 """""" 

406 UNIXPageant = "UNIXPageant" 

407 """""" 

408 OpenSSHAgent = "OpenSSHAgent" 

409 """""" 

410 Pageant = "Pageant" 

411 """""" 

412 OpenSSHAgentOnWindows = "OpenSSHAgentOnWindows" 

413 """""" 

414 StubbedSSHAgent = "StubbedSSHAgent" 

415 """""" 

416 

417 

418class KnownSSHAgentInstance(str, enum.Enum): 

419 """Known SSH agent instances, as test cases/configurations. 

420 

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. 

445 

446 """ 

447 

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 """""" 

464 

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) 

489 

490 

491class SpawnedSSHAgentInfo(NamedTuple): 

492 """Info about a spawned SSH agent, as provided by some fixtures. 

493 

494 Differs from [`RunningSSHAgentInfo`][] in that this info object 

495 already provides a functional client connected to the agent, but not 

496 the address. 

497 

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. 

509 

510 """ 

511 

512 agent_type: KnownSSHAgentType 

513 """""" 

514 client: ssh_agent.SSHAgentClient 

515 """""" 

516 isolated: bool 

517 """""" 

518 

519 

520class RunningSSHAgentInfo(NamedTuple): 

521 """Info about a running SSH agent, as provided by some fixtures. 

522 

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. 

527 

528 Attributes: 

529 socket: 

530 A socket address to connect to the agent. 

531 agent_type: 

532 The agent's type. 

533 

534 """ 

535 

536 socket: str | type[_types.SSHAgentSocket] 

537 """""" 

538 agent_type: KnownSSHAgentType 

539 """""" 

540 

541 def require_external_address(self) -> str: # pragma: no cover 

542 if not isinstance(self.socket, str): 

543 import pytest # noqa: PLC0415 

544 

545 pytest.skip( 

546 reason="This test requires a real, externally resolvable " 

547 "address for the SSH agent socket." 

548 ) 

549 return self.socket 

550 

551 

552class AgentProtocolRequest(NamedTuple): 

553 """A request for the SSH agent protocol. 

554 

555 Attributes: 

556 code: 

557 The expected request code. 

558 payload: 

559 The expected payload. Optional. 

560 

561 """ 

562 

563 code: _types.SSH_AGENTC | int 

564 """""" 

565 payload: bytes 

566 """""" 

567 

568 

569class AgentProtocolResponse(NamedTuple): 

570 """A response for the SSH agent protocol. 

571 

572 Attributes: 

573 code: 

574 The desired response code. 

575 payload: 

576 The desired response payload. 

577 

578 """ 

579 

580 code: _types.SSH_AGENT | int 

581 """""" 

582 payload: bytes 

583 """""" 

584 

585 

586# Vault configurations 

587# ==================== 

588 

589 

590class ValidationSettings(NamedTuple): 

591 """Validation settings for [`VaultTestConfig`][]s. 

592 

593 Attributes: 

594 allow_unknown_settings: 

595 See [`_types.validate_vault_config`][]. 

596 

597 """ 

598 

599 allow_unknown_settings: bool 

600 """""" 

601 

602 

603class VaultTestConfig(NamedTuple): 

604 """A (not necessarily valid) sample vault config, plus metadata. 

605 

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`][]. 

617 

618 """ 

619 

620 config: Any 

621 """""" 

622 comment: str 

623 """""" 

624 validation_settings: ValidationSettings | None 

625 """""" 

626 

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 } 

633 

634 def is_smudgable(self) -> bool: 

635 """Return true if this vault test config can be effectively smudged. 

636 

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. 

640 

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 ) 

650 

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]) 

654 

655 

656# Data objects 

657# ============ 

658 

659 

660# SSH agent socket provider data 

661# ------------------------------ 

662 

663 

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""" 

675 

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""" 

687 

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""" 

697 

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""" 

709 

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""" 

724 

725# SSH test keys 

726# ------------- 

727 

728 

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. 

1397 

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. 

1401 

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. 

1407 

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. 

1411 

1412""" 

1413 

1414 

1415# Vault test configurations 

1416# ------------------------- 

1417 

1418 

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.""" 

1669 

1670 

1671# Common vault sample settings, passphrases, results, etc. 

1672# -------------------------------------------------------- 

1673 

1674 

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""" 

1734 

1735 

1736# Vault native configuration storage data 

1737# --------------------------------------- 

1738 

1739 

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""" 

1856 

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. 

1909 

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""" 

1916 

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. 

1974 

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""" 

1980 

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. 

2038 

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""" 

2044 

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. 

2103 

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""" 

2110 

2111# Error messages 

2112# ============== 

2113 

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"""