{"id":13531549,"url":"https://github.com/sigp/milagro_bls","last_synced_at":"2025-08-06T06:37:19.290Z","repository":{"id":42458885,"uuid":"189912085","full_name":"sigp/milagro_bls","owner":"sigp","description":"BLS12-381 cryptography using Apache Milagro","archived":false,"fork":false,"pushed_at":"2024-02-02T00:44:27.000Z","size":628,"stargazers_count":29,"open_issues_count":3,"forks_count":21,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-27T04:06:31.522Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","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/sigp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2019-06-03T01:02:15.000Z","updated_at":"2024-12-24T23:13:04.000Z","dependencies_parsed_at":"2024-11-02T18:32:05.258Z","dependency_job_id":"7ca24e70-ba2b-4c43-9fb6-99ad2355515f","html_url":"https://github.com/sigp/milagro_bls","commit_stats":null,"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sigp%2Fmilagro_bls","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sigp%2Fmilagro_bls/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sigp%2Fmilagro_bls/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sigp%2Fmilagro_bls/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sigp","download_url":"https://codeload.github.com/sigp/milagro_bls/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246700683,"owners_count":20819921,"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":[],"created_at":"2024-08-01T07:01:03.897Z","updated_at":"2025-04-01T19:32:17.881Z","avatar_url":"https://github.com/sigp.png","language":"Rust","funding_links":[],"categories":["Cryptography"],"sub_categories":["Digital Signature"],"readme":"# BLS12-381 Aggregate Signatures in Rust using Apache Milagro\n\n[![Build Status](https://travis-ci.org/sigp/signature-schemes.svg?branch=master)](https://travis-ci.org/sigp/signature-schemes) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/sigp/lighthouse?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge)\n\n**WARNING: This library is a work in progress and has not been audited. Do NOT consider the cryptography safe!**\n\nUses the [The Apache Milagro Cryptographic Library](https://github.com/apache/incubator-milagro-crypto-rust).\n\nThis crate is heavily based upon work by\n[@lovesh](https://github.com/lovesh).\n\nPresently this library only supports features required for Ethereum 2.0\nsignature validation. The aggregation methods here are vulnerable to the\nrouge-key attack.\n\nThere has been no public audit or scrutiny placed upon this crate. If you're a\ncryptographer I would love to have your input.\n\nThis library uses a Proof of Possession (PoP) variant as protection against rogue key attacks.\nA public key can be PoP verified by signing a hash of the public key. This must be done\nbefore a `PublicKey` may be used in any aggregate signatures.\n\nSubgroup checks are performed for signatures during verification and public keys\nduring deserialisation.\n\n## BLS Standard\n\nCurrent implementation of the BLS Standard aligns with [bls-signatures-v04](https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04)\nand [hash-to-curve-v09](https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-09).\n\n## Usage\n\n### Single Signatures\n\nPerform signing and verification of non-aggregate BLS signatures. Supports\nserializing and de-serializing both public and secret keys.\n\n```rust\nlet sk_bytes = vec![\n\t78, 252, 122, 126, 32, 0, 75, 89, 252, 31, 42, 130, 254, 88, 6, 90, 138, 202, 135, 194,\n\t233, 117, 181, 75, 96, 238, 79, 100, 237, 59, 140, 111,\n];\n\n// Load some keys from a serialized secret key.\nlet sk = SecretKey::from_bytes(\u0026sk_bytes).unwrap();\nlet pk = PublicKey::from_secret_key(\u0026sk);\n\n// Sign a message\nlet message = \"cats\".as_bytes();\nlet signature = Signature::new(\u0026message, \u0026sk);\nassert!(signature.verify(\u0026message, \u0026pk));\n\n// Serialize then de-serialize, just 'cause we can.\nlet pk_bytes = pk.as_bytes();\nlet pk = PublicKey::from_bytes(\u0026pk_bytes).unwrap();\n\n// Verify the message\nassert!(signature.verify(\u0026message, \u0026pk));\n```\n\nGenerate new \"random\" secret keys (see `SecretKey` docs for information on\nentropy sources).\n\n```rust\n// Generate a random key pair.\nlet sk = SecretKey::random(\u0026mut rand::thread_rng());\nlet pk = PublicKey::from_secret_key(\u0026sk);\n\n// Sign and verify a message.\nlet message = \"cats\".as_bytes();\nlet signature = Signature::new(\u0026message, \u0026sk);\nassert!(signature.verify(\u0026message, \u0026pk));\n```\n\n### Aggregate Signatures\n\nAggregate signatures and public keys. Supports serializing and de-serializing\nboth `AggregateSignatures` and `AggregatePublicKeys`.\n\n```rust\nlet signing_secret_key_bytes = vec![\n\t\tvec![\n\t\t\t\t98, 161, 50, 32, 254, 87, 16, 25, 167, 79, 192, 116, 176, 74, 164, 217, 40, 57,\n\t\t\t\t179, 15, 19, 21, 240, 100, 70, 127, 111, 170, 129, 137, 42, 53,\n\t\t],\n\t\tvec![\n\t\t\t\t53, 72, 211, 104, 184, 68, 142, 208, 115, 22, 156, 97, 28, 216, 228, 102, 4, 218,\n\t\t\t\t116, 226, 166, 131, 67, 7, 40, 55, 157, 167, 157, 127, 143, 13,\n\t\t],\n];\n\n// Load the key pairs from our serialized secret keys,\nlet signing_keypairs: Vec\u003cKeypair\u003e = signing_secret_key_bytes\n\t\t.iter()\n\t\t.map(|bytes| {\n\t\t\t\tlet sk = SecretKey::from_bytes(\u0026bytes).unwrap();\n\t\t\t\tlet pk = PublicKey::from_secret_key(\u0026sk);\n\t\t\t\tKeypair { sk, pk }\n\t\t})\n\t\t.collect();\n\nlet message = \"cats\".as_bytes();\n\n// Create an aggregate signature over some message, also generating an\n// aggregate public key at the same time.\nlet mut agg_sig = AggregateSignature::new();\nlet mut public_keys = vec![];\nfor keypair in \u0026signing_keypairs {\n\t\tlet sig = Signature::new(\u0026message, \u0026keypair.sk);\n\t\tagg_sig.add(\u0026sig);\n\t\tpublic_keys.push(keypair.pk.clone());\n}\nlet agg_pub_key = AggregatePublicKey::into_aggregate(\u0026public_keys).unwrap();\n\n// Serialize and de-serialize the aggregates, just 'cause we can.\nlet agg_sig_bytes = agg_sig.as_bytes();\nlet agg_sig = AggregateSignature::from_bytes(\u0026agg_sig_bytes).unwrap();\n\n// Verify the AggregateSignature against the AggregatePublicKey\nassert!(agg_sig.fast_aggregate_verify_pre_aggregated(\u0026message, \u0026agg_pub_key));\n}\n```\n\n### How to Run Benchmarks\n\n```\ncargo bench --features \"bench\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsigp%2Fmilagro_bls","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsigp%2Fmilagro_bls","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsigp%2Fmilagro_bls/lists"}