{"id":30714756,"url":"https://github.com/rub-nds/ssh-client-signatures-artifacts","last_synced_at":"2026-05-11T07:06:08.632Z","repository":{"id":312422293,"uuid":"1022020121","full_name":"RUB-NDS/SSH-Client-Signatures-Artifacts","owner":"RUB-NDS","description":"Artifacts for the paper \"On the Security of SSH Client Signatures\", accepted at the ACM Conference on Computer and Communications Security (CCS) 2025.","archived":false,"fork":false,"pushed_at":"2025-08-30T13:21:29.000Z","size":6267,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-30T15:08:00.369Z","etag":null,"topics":["cryptography","cve-2024-31497","github","gitlab","launchpad","measurement","public-keys","ssh","ssh-client"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RUB-NDS.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-07-18T10:15:58.000Z","updated_at":"2025-08-30T13:21:32.000Z","dependencies_parsed_at":"2025-08-30T15:18:12.195Z","dependency_job_id":null,"html_url":"https://github.com/RUB-NDS/SSH-Client-Signatures-Artifacts","commit_stats":null,"previous_names":["rub-nds/ssh-client-signatures-artifacts"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/RUB-NDS/SSH-Client-Signatures-Artifacts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RUB-NDS%2FSSH-Client-Signatures-Artifacts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RUB-NDS%2FSSH-Client-Signatures-Artifacts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RUB-NDS%2FSSH-Client-Signatures-Artifacts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RUB-NDS%2FSSH-Client-Signatures-Artifacts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RUB-NDS","download_url":"https://codeload.github.com/RUB-NDS/SSH-Client-Signatures-Artifacts/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RUB-NDS%2FSSH-Client-Signatures-Artifacts/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273397843,"owners_count":25098234,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-03T02:00:09.631Z","response_time":76,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cryptography","cve-2024-31497","github","gitlab","launchpad","measurement","public-keys","ssh","ssh-client"],"created_at":"2025-09-03T05:45:14.089Z","updated_at":"2026-05-11T07:06:08.610Z","avatar_url":"https://github.com/RUB-NDS.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# On the Security of SSH Client Signatures - Artifacts\n\n[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.17008443.svg)](https://doi.org/10.5281/zenodo.17008443)\n\nThis repository contains the artifacts for the paper \"On the Security of SSH\nClient Signatures\", accepted at the ACM Conference on Computer and\nCommunications Security (CCS) 2025.\n\n## Prerequisites\n\n### Hardware Requirements\n\nWe recommend having a machine with at least 16 CPU cores and 64 GB of RAM\navailable. This is required to run the Elasticsearch stack and the various\nanalysis tools included in this repository. Running with less than the\nrecommended hardware may result in degraded performance or unpredictable\nresults. Also, we recommend having at least 50 GB of free disk space to avoid\nrunning out of space during experiments.\n\nWe ran our experiments on a server with 2 AMD EPYC 7763 64-core CPUs and 2 TB of\nRAM.\n\n### Software Requirements\n\n- Ubuntu 24.04 LTS. We recommend a fresh installation to avoid possible side\n  effects.\n- Docker 28.3.3 or newer.\n- Golang 1.25.0 or newer.\n- Python 3.11.\n- SageMath 10.3 installed as a Python library.\n\nTo ease installation, we provide a setup script (`scripts/00_setup_env.sh`) that\nautomates the installation of the required software and dependencies. It is\ndesigned to be run on a fresh Ubuntu 24.04 LTS installation. Note that the\ndocker containers require support for modern CPU architectures, please use\nhost-passthrough or similar for the CPU mode in your VM if you do not run on\nnative hardware. In particular, it will perform the following steps:\n\n1. Install system packages\n    - Latest version of Docker\n    - Python 3.11 with venv module installed\n    - SageMath 10.3 dependencies\n2. Install Golang 1.25.0\n3. Sets up a Python virtual environment in `venv/`\n4. Install required Python dependencies for the evaluation scripts and tools\n   into the virtual environment\n5. Install SageMath 10.3 as a Python library\n6. Build the key_scraper and nonce_sampler tools using `go build`\n7. Set up Docker containers for the Elasticsearch and MongoDB infrastructure\n8. Copy the auto-generated Elasticsearch CA certificate to the host\n   (`code/key_scraper/ca.crt`)\n\n\u003e [!IMPORTANT]\n\u003e\n\u003e After running the setup script, you must restart your system to ensure all\n\u003e changes take effect.\n\n\u003e [!TIP]\n\u003e\n\u003e Building SageMath 10.3 as a Python library can take a significant amount of\n\u003e time, please be patient. You may track the progress by tailing the log file\n\u003e (`tail -f logs/setup_env.log`).\n\n### Other Requirements\n\nFor evaluation, accounts on GitHub, GitLab, and Launchpad are required to access\nthe API (GitHub and GitLab only) and to upload generated SSH keys while testing\nfor public key upload restrictions. Free accounts are sufficient for this\npurpose. Uploaded SSH keys should be removed immediately after testing.\n\n### Basic Functionality Test\n\nTo test basic functionality after running `scripts/00_setup_env.sh`, you can\nperform the following checks:\n\n1. Verify that Docker, Golang, and Python are installed and accessible from the\n   command line:\n\n   ```bash\n   docker --version\n   go version\n   python3.11 --version\n   ```\n\n   Expected output (exact versions for Docker and Python can differ):\n\n   ```console\n   user@ccs25ae:~/SSH-Client-Signatures-Artifacts$ docker --version\n   Docker version 28.4.0, build d8eb465\n   user@ccs25ae:~/SSH-Client-Signatures-Artifacts$ go version\n   go version go1.25.0 linux/amd64\n   user@ccs25ae:~/SSH-Client-Signatures-Artifacts$ python3.11 --version\n   Python 3.11.13\n   ```\n\n2. Verify that the Python virtual environment can be activated and, in\n   particular, that you can load the SageMath library:\n\n   ```bash\n   . venv/bin/activate\n   python -c \"from sage.all import Primes; print(Primes())\"\n   deactivate\n   ```\n\n   Expected output:\n\n   ```console\n   user@ccs25ae:~/SSH-Client-Signatures-Artifacts$ . venv/bin/activate\n   (venv) user@ccs25ae:~/SSH-Client-Signatures-Artifacts$ python -c \"from sage.all import Primes; print(Primes())\"\n   Set of all prime numbers: 2, 3, 5, 7, ...\n   (venv) user@ccs25ae:~/SSH-Client-Signatures-Artifacts$ deactivate\n   ```\n\n3. Verify that the Elasticsearch stack is running and that both, Elasticsearch\n   and Kibana, are available:\n\n   ```bash\n   docker ps\n   curl -u elastic:elasticsearchpass --cacert code/key_scraper/ca.crt \"https://localhost:9200/_cluster/health?pretty\"\n   curl \"http://localhost:5601/api/status\"\n   ```\n\n   Expected output:\n\n   ```console\n   user@ccs25ae:~/SSH-Client-Signatures-Artifacts$ docker ps\n   CONTAINER ID   IMAGE                                                 COMMAND                  CREATED          STATUS                             PORTS                                             NAMES\n   aebdf9a4be7e   docker.elastic.co/kibana/kibana:9.1.2                 \"/bin/tini -- /usr/l…\"   11 minutes ago   Up 10 minutes (healthy)            127.0.0.1:5601-\u003e5601/tcp                          sshks-kibana-1\n   3aad35b1244d   docker.elastic.co/elasticsearch/elasticsearch:9.1.2   \"/bin/tini -- /usr/l…\"   11 minutes ago   Up 10 minutes (healthy)            9200/tcp, 9300/tcp                                sshks-es03-1\n   5a79993a8353   docker.elastic.co/elasticsearch/elasticsearch:9.1.2   \"/bin/tini -- /usr/l…\"   11 minutes ago   Up 10 minutes (healthy)            9200/tcp, 9300/tcp                                sshks-es02-1\n   57f0fb088fdd   docker.elastic.co/elasticsearch/elasticsearch:9.1.2   \"/bin/tini -- /usr/l…\"   11 minutes ago   Up 10 minutes (healthy)            127.0.0.1:9200-\u003e9200/tcp, 9300/tcp                sshks-es01-1\n   87fa1a955f51   mongo:latest                                          \"docker-entrypoint.s…\"   11 minutes ago   Up 10 minutes                      0.0.0.0:27017-\u003e27017/tcp, [::]:27017-\u003e27017/tcp   sshks-mongodb-1\n   user@ccs25ae:~/SSH-Client-Signatures-Artifacts$ curl -u elastic:elasticsearchpass --cacert code/key_scraper/ca.crt \"https://localhost:9200/_cluster/health?pretty\"\n   {\n     \"cluster_name\": \"sshks-cluster\",\n     \"status\": \"green\",\n     \"timed_out\": false,\n     \"number_of_nodes\": 3,\n     \"number_of_data_nodes\": 3,\n     \"active_primary_shards\": 40,\n     \"active_shards\": 80,\n     \"relocating_shards\": 0,\n     \"initializing_shards\": 0,\n     \"unassigned_shards\": 0,\n     \"unassigned_primary_shards\": 0,\n     \"delayed_unassigned_shards\": 0,\n     \"number_of_pending_tasks\": 0,\n     \"number_of_in_flight_fetch\": 0,\n     \"task_max_waiting_in_queue_millis\": 0,\n     \"active_shards_percent_as_number\": 100.0\n   }\n   user@ccs25ae:~/SSH-Client-Signatures-Artifacts$ curl \"http://localhost:5601/api/status\"\n   {\"status\":{\"overall\":{\"level\":\"available\"}}}\n   ```\n\n\u003e [!WARNING]\n\u003e\n\u003e If Elasticsearch is unreachable, verify that the `vm.max_map_count`\n\u003e limit is set to 262144 or higher. To access the current limit, run\n\u003e `sysctl -n vm.max_map_count`. To increase the limit, run\n\u003e `sysctl -w vm.max_map_count=262144` and persist the setting by adding or\n\u003e updating the `vm.max_map_count=262144` setting in the `/etc/sysctl.conf` file.\n\u003e When running `scripts/00_setup_env.sh` to set up the environment, the script\n\u003e will take care of this.\n\n## Claims\n\nThe following major claims are made with regard to the artifacts:\n\n1. The `key_scraper` tool (`code/key_scraper`) is capable of collecting SSH\n   public keys from multiple platforms (GitHub, GitLab, Launchpad)\n   systematically.\n2. The evaluation pipeline (`code/key_scraper/scripts`) can identify and analyze\n   weak SSH keys based on the methodology described in Section 3.2 in the paper.\n3. The `07-generate-test-keys.py` script can generate a diverse set of SSH keys\n   violating certain properties for testing upload restrictions. At the time of\n   artifact evaluation, these keys were able to reproduce Table 3 in the paper.\n4. The `nonce_sampler` tool (`code/nonce_sampler`) can test ECDSA and EdDSA\n   signatures generated by SSH clients and agents for determinism and potential\n   bias. It can find the biased nonce vulnerability in PuTTY \u003c= 0.80\n   ([CVE-2024-31497](https://www.cve.org/CVERecord?id=CVE-2024-31497)).\n5. The success rate of the\n   [sieve_pred algorithm](https://github.com/malb/bdd-predicate) in the context\n   of the PuTTY biased nonce vulnerability (521-bit nonces, 9 bits biased) is\n   given by Figure 5 in the paper. In particular, the attack always succeeds\n   when at least 60 signatures with biased nonces are available.\n\n\u003e [!TIP]\n\u003e\n\u003e Each claim can be proven by the corresponding experiment with the same number,\n\u003e that is, claim 1 can be proven by E1, claim 2 by E2, and so on.\n\n\u003e [!NOTE]\n\u003e\n\u003e Our paper is based on two full runs of the key scraper evaluation pipeline\n\u003e (claims 1 and 2) in June 2023 and January 2025. Exact reproduction of the\n\u003e results in the paper is not possible due to the changing nature of the source\n\u003e data. Additionally, a full run will require over a month of real time due to\n\u003e API limits. To account for this, the experiments E1 and E2 are designed to\n\u003e demonstrate the capabilities of the proposed tools and methodologies at a\n\u003e small scale reasonable for evaluation.\n\n## Experiments\n\nFor running the artifacts, you can use the provided scripts in the `scripts/`\ndirectory. Each script is designed to perform a specific task in the evaluation\npipeline.\n\n### E1 - Collecting SSH Public Keys\n\n\u003e [!NOTE]\n\u003e\n\u003e - Estimated time required: 24 hours (adjustable)\n\u003e - Interaction required: yes, initial API token generation\n\u003e   (estimate: 10 minutes)\n\u003e - Other requirements: Internet access, API tokens on GitHub / GitLab\n\u003e - Proves claim: C1 via inspection of the scraped data\n\nTo collect SSH public keys from GitHub, GitLab and Launchpad, you can use the\n`scripts/01_run_scraper.sh` script. This script will configure and then start\nthe key scraper and collect SSH public keys from the platforms for a duration of\n24 hours. To adjust the execution time, pass a duration value to the script,\ne.g. `scripts/01_run_scraper.sh 2h` (any duration value compatible with the\n`timeout` utility is supported, see\n[the corresponding man page](https://linux.die.net/man/1/timeout)). Adjust the\ntimeout in the script as needed (or remove entirely).\n\nTo run the scraper on GitHub and GitLab, you will need to provide a personal\naccess token to authenticate with the API of each service. Refer to\n[GitHub Docs](https://docs.github.com/en/rest/authentication/authenticating-to-the-rest-api?apiVersion=2022-11-28#authenticating-with-a-personal-access-token)\nand [GitLab Docs](https://docs.gitlab.com/user/profile/personal_access_tokens/)\nfor more information on how to generate one. For GitHub, we used a classic\naccess token rather than a fine-grained one - if you decide to generate a\nfine-grained token, selecting public repository access and no account\npermissions should be sufficient. For GitLab, you must assign at least\n`read_api` and `read_user` scopes to the access token.\n\n\u003e [!NOTE]\n\u003e\n\u003e Since our evaluation in January 2025, GitLab started to enforce\n\u003e stricter rate limits on their API, which may negatively affect the data\n\u003e collection process. See\n\u003e [their announcement](https://about.gitlab.com/blog/rate-limitations-announced-for-projects-groups-and-users-apis/)\n\u003e for further details. Our testing indicates that these rate limits only slow\n\u003e down, but not prevent, the data collection process.\n\nAfter execution, the Elasticsearch database should be populated with user\nrecords from all three platforms containing their SSH public keys. You can use\nKibana (available at `http://localhost:5601`) to explore the collected dataset.\nUse `elastic:elasticsearchpass` as the credentials to log in. Navigate to the\n\"Discover\" app (`http://localhost:5601/app/discover`) and create a new data view\n(see\n[Elastic Docs](https://www.elastic.co/docs/explore-analyze/find-and-organize/data-views))\nwith an `sshks_users*` index pattern. For the timestamp field, select\n`visitedAt`.\n\n### E2 - Running the Evaluation Pipeline\n\n\u003e [!NOTE]\n\u003e\n\u003e - Estimated time required: 1 hour (depending on available CPU cores)\n\u003e - Interaction required: no\n\u003e - Other requirements: none\n\u003e - Proves claim: C2 via result files in `results/`\n\nOnce you have collected a decent amount of SSH public keys, run the evaluation\nby pipeline by calling `scripts/02_evaluate_keys.sh`. This script will perform a\nfull run of the evaluation pipeline on the keys collected by the key scraper\ntool. In particular, it will perform the following steps:\n\n1. Activate the virtual environment in `venv`\n2. Extract the SSH keys from the user-oriented scraping results\n   (`01-extract-keys-sshks.py`). Errors are logged to\n   `results/01-extract-keys-sshks-errors.txt`\n3. Collect unique SSH keys and stores it into a separate index\n   (`01-extract-keys-sshks-unique.py`).\n4. Evaluate basic statistics for the dataset (`02-summarize-keys.py`):\n    - `results/02-summary-ecdsa-curve-dist.png` - Distribution of ECDSA key\n      curves used in the collected SSH keys (Figure 4 in the paper).\n    - `results/02-summary-rsa-modulus-cdf.png` - (Complementary) CDF of RSA key\n      modulus sizes used in the collected SSH keys.\n    - `results/02-summary-rsa-modulus-dist.png` - Distribution of RSA key\n      modulus sizes used in the collected SSH keys (Figure 3 in the paper).\n    - `02-summary.tex` - LaTeX table used as a base for Table 2 in the paper.\n5. Analyze the SSH keys according to the methodology described in Section 3.2 of\n   the paper.\n6. Generate a report summarizing the findings of the evaluation pipeline.\n7. Collect users affected by weak keys from the Elasticsearch database for\n   disclosure.\n\nAll results can be found in the `results` directory after running the script.\nAdditionally, the summarized findings are printed to stdout.\n\n### E3 - Testing Public Key Upload Restrictions\n\n\u003e [!NOTE]\n\u003e\n\u003e - Estimated time required: 1 hour\n\u003e - Interaction required: yes, uploading test keys to platforms\n\u003e   (estimate: 20 minutes per platform)\n\u003e - Other requirements: accessible account on GitHub, GitLab, and Launchpad\n\u003e - Proves claim: C3 by comparison between the platforms' responses and Table 3\n\u003e   in the paper\n\nTo test the public key upload restrictions of various platforms, you can\ngenerate SSH keys with specific properties (e.g., weak keys) and attempt to\nupload them to the platforms. To generate the keys, run\n`scripts/03_generate_test_keys.sh`. This will call the\n`07-generate-test-keys.py` python script and store the generated keys in the\n`results` directory. The resulting file contains one SSH key per line that can\nbe copied into the corresponding SSH key upload forms on\n[GitHub](https://github.com/settings/ssh/new),\n[GitLab](https://gitlab.com/-/user_settings/ssh_keys), and Launchpad\n(\u003chttps://launchpad.net/~*user*/+editsshkeys\u003e). If the key is accepted without\nerror and is visible in the account's list of SSH keys, we consider the upload\nsuccessful. Uploading each key to each platform can reproduce Table 3 in the\npaper.\n\nThe file format of the resulting `07-test-keys.txt` file is based on OpenSSH's\n`known_hosts` file. In this format, each line contains a single key with an\nexplicit key type and comment. The format is `\u003ckey type\u003e \u003ckey\u003e \u003ccomment\u003e` where\n`\u003ckey type\u003e` is either `ssh-dss` (for DSA keys), `ssh-rsa` (for RSA keys),\n`ecdsa-sha2-nistp256` (for ECDSA keys), or `ssh-ed25519` (for Ed25519 keys). The\ncomment contains a short description of the key and allows matching the key to\nthe entries in Table 3.\n\n### E4 - Testing SSH Clients and Agents for Nonce Determinism and Bias\n\n\u003e [!NOTE]\n\u003e\n\u003e - Estimated time required: 5 - 30 minutes / client\n\u003e - Interaction required: yes, installing clients and performing connections\n\u003e - Proves claim: C4 by comparison between the output of the script and Table 4\n\u003e   in the paper\n\nTo test an SSH client or agent for nonce determinism and bias, run\n`scripts/04_measure_client_agent.sh`. The script ask for which algorithm the\n`nonce_sampler` tool should be invoked and whether the implementation to test is\na client or agent.\n\nIf client is selected, the tool will listen on port 2200 for incoming client\nconnections. Connect to the tool using your preferred SSH client with the\nselected key configured for authentication (the full key path will be printed\nduring script execution). During the first connection, the tool will try to\ndetermine the nonce generation algorithm used by the client. Manually terminate\nthe SSH client connection if the tool is stuck in the signature collection phase\n(in these cases, the client continuously tries to authenticate in the same\nconnection).\n\nAfterward, the tool will measure nonce bias. Connect to port 2200 using the same\nSSH client. Depending on the client, manual interaction with the client is\nnecessary as some clients do not support partial authentication or limit the\nnumber of authentication attempts in a single connection. Once the required\nnumber of signatures has been collected (indicated by the `remaining:` counter),\nterminate any client connection and the tool will proceed to the nonce bias\nmeasurement phase.\n\nAs an example, the following commands cause the local OpenSSH client to connect\nto the nonce_sampler tool using the NIST P-256 key (adjust as necessary):\n\n```bash\nssh -i code/nonce_sampler/keys/id_ecdsa_nistp256 -p 2200 sample@localhost\n# Abort after a few seconds using Ctrl+C\nssh -i code/nonce_sampler/keys/id_ecdsa_nistp256 -p 2200 sample@localhost\n# Wait until remaining \u003c 0, then terminate using Ctrl+C\n```\n\nIf agent is selected, the tool will automatically try to connect to the UNIX\nsocket given by the $SSH_AUTH_SOCK environment variable. Make sure the SSH agent\nis running before running the script. The tool will try to load the\ncorresponding key into the agent using the SSH agent protocol. If the agent uses\npreconfigured keys only, make sure to load the key before running the script. To\ntest a Windows-based agent, connect to the VM via SSH with agent forwarding\nenabled. This will automatically set the $SSH_AUTH_SOCK in the shell session.\n\nAs an example, the following commands can be used to start the OpenSSH\nssh-agent. ssh-agent support adding keys dynamically through the SSH agent\nprotocol. Hence, adding the keys before running the script is not necessary.\n\n```bash\neval \"$(ssh-agent -s)\"\n```\n\nWhen testing PuTTY 0.80, the script should output a biased nonce with the top 9\nbits of the nonce being zero all the time and k_proto for the nonce generation\nmethod. For all other clients tested, the tool should not report any bias, while\nreporting the nonce generation method as in Table 4 in the paper. Similarly, the\nnonce generation method of an agent should coincide with the one given in Table\n5.\n\n\u003e [!TIP]\n\u003e\n\u003e PuTTY uses a proprietary key format (.ppk) for private keys and cannot use\n\u003e keys generated by `ssh-keygen` directly. In the `00_setup_env.sh` script,\n\u003e `ssh-keygen` is used to bootstrap the evaluation keys. Therefore, to test\n\u003e determinism and bias of a PuTTY client, these keys must be converted to the\n\u003e PuTTY format before use. To do so, run the following command inside the\n\u003e artifact's root directory. It will convert the private keys into PuTTY's .ppk\n\u003e format, which must then be used inside PuTTY.\n\u003e\n\u003e ```bash\n\u003e find code/nonce_sampler/keys -maxdepth 1 -type f -not -name \\*.pub -not -name \\*.ppk -exec puttygen {} -o {}.ppk -O private \\;\n\u003e ```\n\u003e\n\u003e If the `puttygen` executable is not available in your `PATH` (for example, if\n\u003e you build PuTTY from source), adjust the command to include the relative or\n\u003e absolute path.\n\nYou can also find a pre-recorded demonstration of us running experiment E4 against\na Windows-based PuTTY client [in the supp_material folder](supp_material/demo_putty_nonce_measurement.mp4).\n\nWe cannot provide the tested SSH clients and agents as part of these artifacts\ndue to licensing restrictions. However, the following tables based on Tables 4\nand 5 in the paper may be helpful in reproducing the results:\n\n| Client Name         | Version   | OS      | Nonce Scheme                          | Download Link                                                                                            |\n|---------------------|-----------|---------|---------------------------------------|----------------------------------------------------------------------------------------------------------|\n| AbsoluteTelnet      | 12.16     | Windows | *Not RFC 6979 / k_proto*              | [Link](https://www.celestialsoftware.net/telnet/AbsoluteTelnet12.16.exe)                                 |\n| AsyncSSH            | 2.18.0    | Linux   | Random                                | [Link](https://github.com/ronf/asyncssh/archive/refs/tags/v2.18.0.zip)                                   |\n| Bitvise             | 9.42      | Windows | *Not RFC 6979 / k_proto*              | [Link](https://dl.bitvise.com/BvSshClient-942.exe)                                                       |\n| Cyberduck           | 9.0.1     | Windows | Random                                | [Link](https://update.cyberduck.io/windows/Cyberduck-Installer-9.0.1.41941.exe)                          |\n| Dropbear            | 2024.86   | Linux   | Random                                | [Link](https://github.com/mkj/dropbear/archive/refs/tags/DROPBEAR_2024.86.zip)                           |\n| Erlang/OTP SSH      | 5.2.1     | Linux   | *Not RFC 6979 / k_proto*              | [Link](https://github.com/erlang/otp/archive/refs/tags/OTP-27.0.1.zip)                                   |\n| FileZilla           | 3.67.0    | Windows | Random                                | [Link](https://filezilla-project.org/download.php?show_all=1) (*current version only*)                   |\n| Golang x/crypto/ssh | 0.29.0    | Windows | Optional (Any)                        | [Link](https://github.com/golang/crypto/archive/refs/tags/v0.29.0.zip)                                   |\n| libssh              | 0.11.1    | Linux   | Random (OpenSSL) / RFC 6979 (MBedTLS) | [Link](https://www.libssh.org/files/0.11/libssh-0.11.1.tar.xz)                                           |\n| OpenSSH Portable    | 9.9p1     | Linux   | Random                                | [Link](https://github.com/openssh/openssh-portable/archive/refs/tags/V_9_9_P1.zip)                       |\n| OpenSSH Portable    | 9.9p1     | MacOS   | Random                                | [Link](https://github.com/apple-oss-distributions/OpenSSH/archive/refs/tags/OpenSSH-346.zip)             |\n| Paramiko            | 3.5.0     | Linux   | Random                                | [Link](https://github.com/paramiko/paramiko/archive/refs/tags/3.5.0.zip)                                 |\n| PKIX-SSH            | 15.3      | Linux   | Random                                | [Link](https://gitlab.com/secsh/pkixssh/-/archive/v15.3/pkixssh-v15.3.zip)                               |\n| PortX               | 2.2.12    | MacOS   | Random                                | [Link](https://apps.apple.com/us/app/portx-ssh-sftp-client/id1566480505) (*current version only*)        |\n| PuTTY               | 0.80      | Windows | k_proto                               | [Link](https://the.earth.li/~sgtatham/putty/0.80/w64/putty-64bit-0.80-installer.msi)                     |\n| PuTTY               | 0.81      | Windows | RFC 6979                              | [Link](https://the.earth.li/~sgtatham/putty/0.81/w64/putty-64bit-0.81-installer.msi)                     |\n| SecureCRT           | 9.5.2     | Windows | Random                                | [Link](https://www.vandyke.com/cgi-bin/releases.php?product=securecrt) (*current version only*)          |\n| Secure Shellfish    | 2025.17   | MacOS   | *Not RFC 6979 / k_proto*              | [Link](https://apps.apple.com/de/app/ssh-files-secure-shellfish/id1336634154) (*current version only*)   |\n| ServerCat           | 1.18      | MacOS   | *Not RFC 6979 / k_proto*              | [Link](https://apps.apple.com/de/app/servercat-ssh-terminal/id1501532023) (*current version only*)       |\n| SSH Term            | 7.0.26    | MacOS   | *Not RFC 6979 / k_proto*              | [Link](https://apps.apple.com/d3/app/ssh-term-secure-remote-shell/id1638226840) (*current version only*) |\n| Tectia SSH          | 6.6.3.490 | Windows | Random                                | [Link](https://info.ssh.com/tectia-ssh-client-server-trial-download) (*current version only* / *trial*)  |\n| Tera Term           | 5.2       | Windows | Random                                | [Link](https://github.com/TeraTermProject/teraterm/releases/download/v5.2/teraterm-5.2.exe)              |\n| Termius             | 9.8.5     | Linux   | Random                                | [Link](https://www.termius.com/download/linux/Termius.deb) (*current version only*)                      |\n| Termius             | 9.21.2    | MacOS   | Random                                | [Link](https://apps.apple.com/de/app/termius-modern-ssh-client/id549039908) (*current version only*)     |\n| Win32 OpenSSH       | 9.5.0.0   | Windows | Random                                | [Link](https://github.com/PowerShell/Win32-OpenSSH/archive/refs/tags/v9.5.0.0p1-Beta.zip)                |\n| WinSCP              | 6.3.4     | Windows | RFC 6979                              | [Link](https://sourceforge.net/projects/winscp/files/WinSCP/6.5.2/WinSCP-6.5.2-Setup.exe/download)       |\n| XShell 7            | 0170      | Windows | Random                                | [Link](https://www.netsarang.com/en/xshell-download/) (*current version only* / *trial*)                 |\n\n| Agent Name      | Version   | OS      | Nonce Scheme         | Download Link                                                                                                             |\n|-----------------|-----------|---------|----------------------|---------------------------------------------------------------------------------------------------------------------------|\n| 1Password       | 8.10.56   | Linux   | *No (EC)DSA support* | [Link](https://downloads.1password.com/linux/debian/amd64/stable/1password-latest.deb) (*current version only* / *trial*) |\n| GnuPG           | 2.4.4     | Linux   | RFC 6979             | [Link](https://gnupg.org/ftp/gcrypt/gnupg/gnupg-2.4.4.tar.bz2)                                                            |\n| Goldwarden      | 0.3.6     | Linux   | Random               | [Link](https://github.com/quexten/goldwarden/releases/download/v0.3.6/goldwarden_0.3.6_amd64.deb)                         |\n| KeeAgent        | 0.13.8    | Linux   | Random               | [Link](https://github.com/dlech/KeeAgent/releases/download/v0.13.8/KeeAgent_v0.13.8.zip)                                  |\n| MobaXTerm       | 24.4      | Windows | RFC 6979             | [Link](https://download.mobatek.net/2522025040602403/MobaXterm_Portable_v25.2.zip) (*current version only*)               |\n| OpenSSH         | 9.6p1     | Linux   | Random               | [Link](https://github.com/openssh/openssh-portable/archive/refs/tags/V_9_6_P1.zip)                                        |\n| PKIX-SSH        | 15.3      | Linux   | Random               | [Link](https://gitlab.com/secsh/pkixssh/-/archive/v15.3/pkixssh-v15.3.zip)                                                |\n| PuTTY Pageant   | 0.80      | Windows | k_proto              | [Link](https://the.earth.li/~sgtatham/putty/0.80/w64/putty-64bit-0.80-installer.msi)                                      |\n| PuTTY Pageant   | 0.81      | Windows | RFC 6979             | [Link](https://the.earth.li/~sgtatham/putty/0.81/w64/putty-64bit-0.81-installer.msi)                                      |\n| SecureCRT       | 9.5.2     | Windows | Random               | [Link](https://www.vandyke.com/cgi-bin/releases.php?product=securecrt) (*current version only*)                           |\n| Tectia SSH      | 6.6.3.490 | Windows | Random               | [Link](https://info.ssh.com/tectia-ssh-client-server-trial-download) (*current version only* / *trial*)                   |\n| Termius         | 9.9.0     | Linux   | Random               | [Link](https://www.termius.com/download/linux/Termius.deb) (*current version only*)                                       |\n| Win32 OpenSSH   | 9.5.0.0   | Windows | Random               | [Link](https://github.com/PowerShell/Win32-OpenSSH/archive/refs/tags/v9.5.0.0p1-Beta.zip)                                 |\n| XShell 7 Xagent | 0170      | Windows | Random               | [Link](https://www.netsarang.com/en/xshell-download/) (*current version only* / *trial*)                                  |\n\n### E5 - PuTTY Vulnerability Success Rate Benchmarking\n\n\u003e [!NOTE]\n\u003e\n\u003e - Estimated time required: 6 hours\n\u003e - Interaction required: no\n\u003e - Proves claim: C5 by comparison between the output of the script and Figure 5\n\u003e   in the paper\n\nTo benchmark the success rate of the PuTTY vulnerability, run\n`scripts/05_bench_biased_nonce.sh`. This will invoke the `ecdsa_cli.py` script\nfrom the [bdd-predicate](https://github.com/malb/bdd-predicate) repository with\nthe PuTTY-specific parameters, and with a varying number of available signatures\n(ranging from 56 to 64 signatures).\n\nDepending on the number of available CPU cores, each run may take significant\ntime to complete. With 16 cores on a desktop machine, each run may take around\n15-20 minutes to complete. You can run\n`tail -f results/putty_attack/bdd-sieve_pred-$i.out` (where $i is the number of\navailable signatures `m` in the current run) to monitor the progress of each\nbenchmark.\n\nAfter completing the benchmarks, the success rate for each run will be printed\nto stdout. The data points should closely resemble the ones reported in the\npaper in Figure 5.\n\n## Repository Structure\n\n```text\n.\n├── code\n│   ├── env_docker                 # Dockerfiles for creating the Elasticsearch infrastructure used for evalutaion\n│   ├── key_scraper                # A tool written in Go that can collect SSH public keys from GitHub, GitLab, and Launchpad\n|   |   └── scripts                # Scripts for evaluating a dataset of SSH public keys gathered with the key_scraper tool\n│   ├── nonce_sampler              # A tool written in Go that can be used to analyze the determinism and bias of SSH client nonces\n│   └── rsa_factorability_tool     # Python implementation for an optimized batch-gcd algorithm used to find common factors\n├── data\n│   ├── key_scraper_results        # Experimental results of the key_scraper used in the paper (excluding raw data)\n│   └── putty_attack               # Experimental results with regard to the PuTTY vulnerability\n├── scripts\n│   ├── 00_setup_env.sh            # Script for setting up a fresh evaluation environment with all dependencies installed\n│   ├── 01_run_scraper.sh          # Runs the key_scraper tool on GitHub, Gitlab, and Launchpad for 24 hours\n│   ├── 02_evaluate_keys.sh        # Performs a full run of the evaluation pipeline on the keys collected by the key_scraper tool\n│   ├── 03_generate_test_keys.sh   # Generates test keys for testing public key upload restrictions\n│   ├── 04_measure_client_agent.sh # Runs the nonce_sampler tool to measure client nonce determinism and bias\n│   └── 05_bench_biased_nonce.sh   # Benchmarks the success rate of the PuTTY vulnerability as described in the paper\n├── supp_material                  # Contains additional material that did not make it into the final version of the paper but may be of interest\n└── README.md\n```\n\n## Acknowledgements\n\nWe use a variety of third party libraries and tools for the tools and scripts\ncontained in this repository.\n\n### Key Scraper (`code/key_scraper`)\n\n- GraphQL Client -\n  [github.com/Khan/genqlient](https://github.com/Khan/genqlient)\n- Golang Elasticsearch Library -\n  [github.com/elastic/go-elasticsearch](https://github.com/elastic/go-elasticsearch)\n- Scheduling Library -\n  [github.com/reugn/go-quartz](https://github.com/reugn/go-quartz)\n- Configuration Library -\n  [github.com/spf13/viper](https://github.com/spf13/viper)\n- GraphQL Parser -\n  [github.com/vektah/gqlparser](https://github.com/vektah/gqlparser)\n\n### Key Scraper Evaluation Scripts (`code/key_scraper/scripts`)\n\n- badkeys Tool - [badkeys](https://pypi.org/project/badkeys/)\n- Cryptographic Library -\n  [cryptography](https://pypi.org/project/cryptography/)\n- Elliptic Curve Library - [ECPy](https://pypi.org/project/ECPy/)\n- Python Elasticsearch Library -\n  [elasticsearch](https://pypi.org/project/elasticsearch/)\n- Multi-precision Arithmetic Library - [gmpy2](https://pypi.org/project/gmpy2/)\n- Plotting Library - [matplotlib](https://pypi.org/project/matplotlib/)\n- Multiprocessing Library - [mpire](https://pypi.org/project/mpire/)\n- NumPy - [numpy](https://pypi.org/project/numpy/)\n- ROCA Detection Library - [roca-detect](https://pypi.org/project/roca-detect/)\n- Progress Bar - [tqdm](https://pypi.org/project/tqdm/)\n\n### RSA Factorability Tool (`code/rsa_factorability_tool`)\n\n- badkeys Tool - [badkeys](https://pypi.org/project/badkeys/)\n- Cryptographic Library -\n  [cryptography](https://pypi.org/project/cryptography/)\n- WSGI Web Application Framework - [Flask](https://pypi.org/project/Flask/)\n- Multi-precision Arithmetic Library - [gmpy2](https://pypi.org/project/gmpy2/)\n- Python MongoDB Library - [pymongo](https://pypi.org/project/pymongo/)\n- WSGI Server - [waitress](https://pypi.org/project/waitress/)\n- Integer Factorization - [primefac](https://pypi.org/project/primefac/)\n- Progress Bar - [tqdm](https://pypi.org/project/tqdm/)\n- Python Elasticsearch Library -\n  [elasticsearch](https://pypi.org/project/elasticsearch/)\n\n### Client Nonce Sampler (`code/nonce_sampler`)\n\n- Implementation of the Edwards25519 Curve -\n  [filippo.io/edwards25519](https://filippo.io/edwards25519)\n- Colorized Output - [github.com/fatih/color](https://github.com/fatih/color)\n- Tabular Output - [github.com/rodaine/table](https://github.com/rodaine/table)\n- CLI Interface - [github.com/urfave/cli](https://github.com/urfave/cli)\n- Queue Implementation - [go.linecorp.com/garr](https://go.linecorp.com/garr)\n- Cryptographic Library / SSH Implementation -\n  [golang.org/x/crypto](https://golang.org/x/crypto) (modified)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frub-nds%2Fssh-client-signatures-artifacts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frub-nds%2Fssh-client-signatures-artifacts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frub-nds%2Fssh-client-signatures-artifacts/lists"}