{"id":20113806,"url":"https://github.com/mkj/caprand","last_synced_at":"2025-05-06T12:30:40.974Z","repository":{"id":150881739,"uuid":"557847500","full_name":"mkj/caprand","owner":"mkj","description":"RP2040 entropy source","archived":false,"fork":false,"pushed_at":"2025-03-20T11:44:49.000Z","size":1608,"stargazers_count":6,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-09T12:21:56.331Z","etag":null,"topics":["entropy","random","rp2040"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"0bsd","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mkj.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}},"created_at":"2022-10-26T12:21:43.000Z","updated_at":"2025-03-20T11:44:52.000Z","dependencies_parsed_at":"2024-02-18T06:23:57.467Z","dependency_job_id":"19a3b8f5-bb67-4038-a8f8-8f7bd218b4ae","html_url":"https://github.com/mkj/caprand","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkj%2Fcaprand","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkj%2Fcaprand/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkj%2Fcaprand/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkj%2Fcaprand/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mkj","download_url":"https://codeload.github.com/mkj/caprand/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252683391,"owners_count":21788029,"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","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":["entropy","random","rp2040"],"created_at":"2024-11-13T18:26:02.177Z","updated_at":"2025-05-06T12:30:40.227Z","avatar_url":"https://github.com/mkj.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RP2040 entropy source\n\n[Docs](https://docs.rs/caprand) [`caprand` crate](https://crates.io/crates/caprand)\n\nThis is a random number generator for a RP2040. It requires one hardware component,\na capacitor between a GPIO pin and ground. It should be treated as a proof of concept,\nit requires further analysis before use in applications with consequences.\n\nThis is based on Peter Allan’s [twocent](https://github.com/alwynallan/twocents), with\nhalf the component and pin count.\n\nAn end program would use [getrandom](https://docs.rs/getrandom) with `custom` feature,\nsee [rand](examples/rand.rs) example.\n\n```rust\n    caprand::setup(\u0026mut p.PIN_10).expect(\"RNG setup failed\");\n    getrandom::register_custom_getrandom!(caprand::random);\n    // ...\n    let mut key = [0u8; 32];\n    getrandom::getrandom(\u0026key).unwrap();\n```\n\n## Operation\n\nThere is a capacitor between a GPIO pin and ground.\nThe capacitor is discharged briefly via the GPIO pin pulling low (1 cycle)\nthen the RP2040 internal pullup on that pin brings the capacitor high again.\nIt spins in a tight loop waiting for the pin to read as “high” input.\n\nThe time taken is measured to an exact system clock cycle (125MHz default), in\nbursts of 5 bits (limited by number of registers).  That low order part of the\npullup time is output as a noise sample. Samples are hashed together\nto form a seed, which seeds a [ChaCha20](https://docs.rs/rand_chacha/latest/rand_chacha/struct.ChaCha20Rng.html)\ncryptographic DRBG.\n\n![Oscilloscope capture](docs/50MS-50mv.png)\n\n## Security\n\nThe noise source has not been thoroughly quantified. Empirical testing seems\nto show 1-2 bits per sample. As a workaround it takes 100 noise samples per bit of output,\nhashing 25600 input noise samples to seed the DRBG.\n\n![A 160x160 random square](docs/25600.png)  \n(typical 25600 samples taken from usbnoise example)\n\nBasic health tests (Adaptive Proportion and Repetition) are applied.\n\nThe hardware scheme has no protection against local interference (similar to the RP2040 itself).\n\n## Hardware\n\nTesting was performed with a 10nF Y5V SMD chip capacitor soldered between\nGP10 pad and the adjacent GND pad, on a Pico W board.\nOther capacitor values should also work OK - 100nF was tested, 1nF is likely to work.\n\n![RP Pico with capacitor](docs/pico-cap.jpeg)\n\n## Examples\n\nExamples must be built with `--features defmt`.\n\n[rand](examples/rand.rs) uses getrandom as a normal program would.\n\n[usbnoise](examples/usbnoise.rs) outputs raw samples as hex values, as a USB serial device\n\n[sernoise](examples/sernoise.rs) outputs raw samples as hex values, via the rp2040 uart\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmkj%2Fcaprand","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmkj%2Fcaprand","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmkj%2Fcaprand/lists"}