{"id":37022821,"url":"https://github.com/pgpainless/pgpainless","last_synced_at":"2026-01-14T02:43:48.891Z","repository":{"id":37006188,"uuid":"135846104","full_name":"pgpainless/pgpainless","owner":"pgpainless","description":"Simple to use OpenPGP API based on Bouncy Castle","archived":false,"fork":false,"pushed_at":"2025-12-19T14:25:51.000Z","size":8760,"stargazers_count":193,"open_issues_count":21,"forks_count":30,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-12-21T00:45:35.273Z","etag":null,"topics":["android","bouncy-castle","bouncycastle","encryption","gpg","java","kotlin","openpgp","openpgp-library","pgp","rfc4880","rfc9580","signature","sop"],"latest_commit_sha":null,"homepage":"https://pgpainless.org","language":"Java","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/pgpainless.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":"THREAT_MODEL.md","audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","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},"funding":{"github":"vanitasvitae"}},"created_at":"2018-06-02T19:24:33.000Z","updated_at":"2025-12-17T14:17:37.000Z","dependencies_parsed_at":"2024-04-10T09:39:12.746Z","dependency_job_id":"52fb7016-c4ec-41a5-923f-8374dacab9bf","html_url":"https://github.com/pgpainless/pgpainless","commit_stats":null,"previous_names":[],"tags_count":127,"template":false,"template_full_name":null,"purl":"pkg:github/pgpainless/pgpainless","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pgpainless%2Fpgpainless","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pgpainless%2Fpgpainless/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pgpainless%2Fpgpainless/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pgpainless%2Fpgpainless/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pgpainless","download_url":"https://codeload.github.com/pgpainless/pgpainless/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pgpainless%2Fpgpainless/sbom","scorecard":{"id":553531,"data":{"date":"2025-08-11","repo":{"name":"github.com/pgpainless/pgpainless","commit":"0d807cb6b8317f2e878509b5cb5f4a9a91e5287d"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5.9,"checks":[{"name":"Maintained","score":10,"reason":"9 commit(s) and 7 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 1/29 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":9,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql-analysis.yml:33","Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql-analysis.yml:32","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/depencency-submission.yml:14","Warn: no topLevel permission defined: .github/workflows/codeql-analysis.yml:1","Warn: no topLevel permission defined: .github/workflows/depencency-submission.yml:1","Info: topLevel 'contents' permission set to 'read': .github/workflows/gradle_push.yml:19","Info: topLevel 'contents' permission set to 'read': .github/workflows/pr.yml:18"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":9,"reason":"binaries present in source code","details":["Warn: binary detected: gradle/wrapper/gradle-wrapper.jar:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":4,"reason":"dependency not pinned by hash detected -- score normalized to 4","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:45: update your workflow using https://app.stepsecurity.io/secureworkflow/pgpainless/pgpainless/codeql-analysis.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:49: update your workflow using https://app.stepsecurity.io/secureworkflow/pgpainless/pgpainless/codeql-analysis.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:60: update your workflow using https://app.stepsecurity.io/secureworkflow/pgpainless/pgpainless/codeql-analysis.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:74: update your workflow using https://app.stepsecurity.io/secureworkflow/pgpainless/pgpainless/codeql-analysis.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/depencency-submission.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/pgpainless/pgpainless/depencency-submission.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/depencency-submission.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/pgpainless/pgpainless/depencency-submission.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/gradle_push.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/pgpainless/pgpainless/gradle_push.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/gradle_push.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/pgpainless/pgpainless/gradle_push.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pr.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/pgpainless/pgpainless/pr.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pr.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/pgpainless/pgpainless/pr.yml/main?enable=pin","Info:   0 out of   9 GitHub-owned GitHubAction dependencies pinned","Info:   3 out of   4 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact 1.7.6 not signed: https://api.github.com/repos/pgpainless/pgpainless/releases/212221580","Warn: release artifact 1.7.6 does not have provenance: https://api.github.com/repos/pgpainless/pgpainless/releases/212221580"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":7,"reason":"SAST tool detected but not run on all commits","details":["Info: SAST configuration detected: CodeQL","Warn: 0 commits out of 2 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-20T11:39:58.674Z","repository_id":37006188,"created_at":"2025-08-20T11:39:58.674Z","updated_at":"2025-08-20T11:39:58.674Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408731,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"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":["android","bouncy-castle","bouncycastle","encryption","gpg","java","kotlin","openpgp","openpgp-library","pgp","rfc4880","rfc9580","signature","sop"],"created_at":"2026-01-14T02:43:48.108Z","updated_at":"2026-01-14T02:43:48.883Z","avatar_url":"https://github.com/pgpainless.png","language":"Java","funding_links":["https://github.com/sponsors/vanitasvitae"],"categories":[],"sub_categories":[],"readme":"\u003c!--\nSPDX-FileCopyrightText: 2021 Paul Schaub \u003cinfo@pgpainless.org\u003e\n\nSPDX-License-Identifier: Apache-2.0\n--\u003e\n\n# PGPainless - Use OpenPGP Painlessly!\n\n[![Build Status](https://github.com/pgpainless/pgpainless/actions/workflows/gradle_push.yml/badge.svg)](https://github.com/pgpainless/pgpainless/actions/workflows/gradle_push.yml)\n[![Coverage Status](https://coveralls.io/repos/github/pgpainless/pgpainless/badge.svg?branch=main)](https://coveralls.io/github/pgpainless/pgpainless?branch=main)\n[![Interoperability Test-Suite](https://badgen.net/badge/Sequoia%20Test%20Suite/results/green)](https://tests.sequoia-pgp.org/)\n[![PGP](https://img.shields.io/badge/pgp-A027%20DB2F%203E1E%20118A-blue)](https://keyoxide.org/7F9116FEA90A5983936C7CFAA027DB2F3E1E118A)\n[![REUSE status](https://api.reuse.software/badge/github.com/pgpainless/pgpainless)](https://api.reuse.software/info/github.com/pgpainless/pgpainless)\n[![Documentation Status](https://readthedocs.org/projects/pgpainless/badge/?version=latest)](https://pgpainless.readthedocs.io/en/latest/?badge=latest)\n\n**PGPainless is an easy-to-use OpenPGP library for Java and Android applications**\n\n[![Packaging status](https://repology.org/badge/vertical-allrepos/pgpainless.svg)](https://repology.org/project/pgpainless/versions)\n[![Maven Central](https://badgen.net/maven/v/maven-central/org.pgpainless/pgpainless-core)](https://search.maven.org/artifact/org.pgpainless/pgpainless-core)\n\n## About\n\nPGPainless aims to make using OpenPGP in Java projects as simple as possible.\nIt does so by introducing an intuitive Builder structure, which allows easy \nsetup of encryption/decryption operations, as well as straight forward key generation.\n\nPGPainless is based around the Bouncy Castle java library and can be used on Android.\nIt can be configured to either use the Java Cryptographic Engine (JCE), or Bouncy Castles lightweight reimplementation.\n\nWhile signature verification in Bouncy Castle is limited to signature correctness, PGPainless goes much further.\nIt also checks if signing subkeys are properly bound to their primary key, if keys are expired or revoked, as well as\nif keys are allowed to create signatures in the first place.\n\nThese rigorous checks make PGPainless stand out from other Java-based OpenPGP libraries and are the reason why\nPGPainless currently scores above average on Sequoia-PGPs [Interoperability Test-Suite](https://tests.sequoia-pgp.org).\n\n\u003e At FlowCrypt we are using PGPainless in our Kotlin code bases on Android and on server side.\n\u003e The ergonomics of legacy PGP tooling on Java is not very good, and PGPainless improves it greatly.\n\u003e We were so happy with our initial tests and with Paul - the maintainer, that we decided to sponsor further development of this library.\n\u003e\n\u003e -Tom @ FlowCrypt.com\n\n\u003e Finally, testing irrefutably confirmed that the library removes many associated difficulties with PGP use in its provision of an approachable and uncomplicated API.\n\u003e In this regard, Paul Schaub deserves the utmost praise.\n\u003e\n\u003e -Mario @ Cure53.de\n\n### AI-free!\n\nPGPainless was, is and will continue to be developed without the help of generative AI.\nTraining large language models (LLMs) consumes huge amounts of energy, contributing to pollution of our planet\nthrough the large scale exploitation of fossile fuels.\nFurther, AI data centers are large consumers of water, which - due to the ongoing climate crisis - is becoming a\nscarce resource in many places.\n\nThe author is convinced, that the risk that generative artificial intelligence poses on society is greater than its\nbenefits and therefore refrains from using it.\n\nPGPainless is made by humans for humans \u003c3.\n\n## Get Started\n\nThe very easiest way to start using OpenPGP on Java/Kotlin based systems is to use an implementation of [sop-java](https://github.com/pgpainless/sop-java).\n`sop-java` defines a very stripped down API and is super easy to get started with.\nLuckily PGPainless provides an implementation for the `sop-java` interface definitions in the form of [pgpainless-sop](pgpainless-sop/README.md).\n\nIf you need more flexibility, directly using `pgpainless-core` is the way to go.\n\n## Features\n\nMost of PGPainless' features can be accessed directly from the `PGPainless` class.\nIf you want to get started, this class is your friend :)\n\nFor further details you should check out the [javadoc](https://javadoc.io/doc/org.pgpainless/pgpainless-core)!\n\n### Handle Keys\nReading keys from ASCII armored strings or from binary files is easy:\n\n```java\n        String key = \"-----BEGIN PGP PRIVATE KEY BLOCK-----\\n\"...\n        OpenPGPKey secretKey = PGPainless.getInstance().readKey()\n                .parseKey(key);\n```\n\nSimilarly, keys can quickly be exported::\n\n```java\n        OpenPGPKey secretKey = ...;\n        String armored = secretKey.toAsciiArmoredString();\n        byte[] binary = secretKey.getEncoded();\n```\n\nExtract a public key certificate from a secret key:\n\n```java\n        OpenPGPKey secretKey = ...;\n        OpenPGPCertificate certificate = secretKey.toCertificate();\n```\n\n### Easily Generate Keys\nPGPainless comes with a simple to use `KeyRingBuilder` class that helps you to quickly generate modern OpenPGP keys.\nThere are some predefined key archetypes, but it is possible to fully customize key generation to your needs.\n\n```java\n        PGPainless api = PGPainless.getInstance();\n        // RSA key without additional subkeys\n        OpenPGPKey secretKeys = api.generateKey()\n                .simpleRsaKeyRing(\"Juliet \u003cjuliet@montague.lit\u003e\", RsaLength._4096);\n                \n        // EdDSA primary key with EdDSA signing- and XDH encryption subkeys\n        OpenPGPKey secretKeys = api.generateKey()\n                .modernKeyRing(\"Romeo \u003cromeo@montague.lit\u003e\", \"I defy you, stars!\");\n\n        // Customized key\n        OpenPGPKey keyRing = api.buildKey()\n                .setPrimaryKey(KeySpec.getBuilder(\n                        RSA.withLength(RsaLength._8192),\n                        KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER))\n                .addSubkey(\n                        KeySpec.getBuilder(ECDSA.fromCurve(EllipticCurve._P256), KeyFlag.SIGN_DATA)\n                                .overrideCompressionAlgorithms(CompressionAlgorithm.ZLIB)\n                ).addSubkey(\n                        KeySpec.getBuilder(\n                                        ECDH.fromCurve(EllipticCurve._P256),\n                                        KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE)\n                ).addUserId(\"Juliet \u003cjuliet@montague.lit\u003e\")\n                .addUserId(\"xmpp:juliet@capulet.lit\")\n                .setPassphrase(Passphrase.fromPassword(\"romeo_oh_Romeo\u003c3\"))\n                .build();\n```\n\n### Encrypt and Sign Data\nPGPainless makes it easy and painless to encrypt and/or sign data.\nPassed in keys are automatically evaluated, so that you don't accidentally encrypt to revoked or expired keys.\nPGPainless will furthermore detect which algorithms are supported by recipient keys and will negotiate\nalgorithms accordingly.\nStill it allows you to manually specify which algorithms to use of course.\n\n```java\n        PGPainless api = PGPainless.getInstance();\n        EncryptionStream encryptionStream = api.generateMessage()\n                .onOutputStream(outputStream)\n                .withOptions(\n                        ProducerOptions.signAndEncrypt(\n                                EncryptionOptions.get(api)\n                                        .addRecipient(aliceKey)\n                                        .addRecipient(bobsKey)\n                                        // optionally encrypt to a passphrase\n                                        .addMessagePassphrase(Passphrase.fromPassword(\"password123\"))\n                                        // optionally override symmetric encryption algorithm\n                                        .overrideEncryptionAlgorithm(SymmetricKeyAlgorithm.AES_192),\n                                SigningOptions.get(api)\n                                        // Sign in-line (using one-pass-signature packet)\n                                        .addInlineSignature(secretKeyDecryptor, aliceSecKey, signatureType)\n                                        // Sign using a detached signature\n                                        .addDetachedSignature(secretKeyDecryptor, aliceSecKey, signatureType)\n                                        // optionally override hash algorithm\n                                        .overrideHashAlgorithm(HashAlgorithm.SHA256),\n                                api\n                        ).setAsciiArmor(true) // Ascii armor or not\n                );\n\n        Streams.pipeAll(plaintextInputStream, encryptionStream);\n        encryptionStream.close();\n\n        // Information about the encryption (algorithms, detached signatures etc.)\n        EncryptionResult result = encryptionStream.getResult();\n```\n\n### Decrypt and Verify Signatures\n\nDecrypting data and verifying signatures is being done similarly.\nPGPainless will not only verify *correctness* of signatures, but also if the signing key was allowed to create the signature.\nA key might not be allowed to create signatures if, for example, it expired or was revoked, or was not properly bound to the key ring.\nFurthermore, PGPainless will reject signatures made using weak algorithms like SHA-1. \nThis behaviour can be modified though using the `Policy` class.\n\n```java\n        DecryptionStream decryptionStream = PGPainless.getInstance().processMessage()\n                .onInputStream(encryptedInputStream)\n                .withOptions(ConsumerOptions.get(api)\n                        .addDecryptionKey(bobSecKeys, secretKeyProtector)\n                        .addVerificationCert(alicePubKeys)\n                );\n\n        Streams.pipeAll(decryptionStream, outputStream);\n        decryptionStream.close();\n\n        // Result contains information like signature status etc.\n        MessageMetadata metadata = decryptionStream.getMetadata();\n```\n\n*After* the `DecryptionStream` was closed, you can get metadata about the processed data by retrieving the `MessageMetadata`.\nAgain, this object will contain information about how the message was encrypted, who signed it and so on.\n\n#### Many more examples can be found in the [examples package](pgpainless-core/src/test/java/org/pgpainless/example)!!!\n\n## Include PGPainless in your Project\n\nPGPainless is available on maven central. In order to include it in your project, just add the \nmaven central repository and add PGPainless as a dependency.\n\n```gradle\nrepositories {\n\tmavenCentral()\n}\n\ndependencies {\n\timplementation 'org.pgpainless:pgpainless-core:1.7.6'\n}\n```\n\n## Professional Support\nDo you need a custom feature? Are you unsure of what's the best way to integrate PGPainless into your product?\nWe offer paid professional services. Don't hesitate to send an inquiry to [info@pgpainless.org](mailto:info@pgpainless.org).\n\n## Development\nJoin the projects IRC channel [**#pgpainless**](ircs://irc.oftc.net:6697/#pgpainless) on OFTC if you have any questions!\n\nPGPainless is developed in - and accepts contributions from - the following places:\n\n* [Github](https://github.com/pgpainless/pgpainless)\n* [Codeberg](https://codeberg.org/PGPainless/pgpainless)\n\nWe are using SemVer (MAJOR.MINOR.PATCH) versioning, although MINOR releases could contain breaking changes from time to time.\n\nIf you want to contribute a bug fix, please check the `release/X.Y` branches first to see, what the oldest release is\nwhich contains the bug you are fixing. That way we can update older revisions of the library easily.\n\nPlease follow the [code of conduct](CODE_OF_CONDUCT.md) if you want to be part of the project.\n\n## Acknowledgements\nIn the past, development on PGPainless has been generously sponsored by [FlowCrypt.com](https://flowcrypt.com). Thank you very very very much!\n[![FlowCrypt Logo](https://warmwasserwerfer.de/wp-content/uploads/2022/05/flowcrypt-logo.svg)](https://flowcrypt.com)\n\nParts of PGPainless development ([project page](https://nlnet.nl/project/PGPainless/)) has been funded by [NGI Assure](https://nlnet.nl/assure/) through [NLNet](https://nlnet.nl).  \nNGI Assure is made possible with financial support from the [European Commission](https://ec.europa.eu/)'s [Next Generation Internet](https://ngi.eu/) programme, under the aegis of [DG Communications Networks, Content and Technology](https://ec.europa.eu/info/departments/communications-networks-content-and-technology_en).\n[![NGI Assure Logo](https://warmwasserwerfer.de/wp-content/uploads/2022/05/NGIAssure_tag.svg)](https://nlnet.nl/assure/)\n\nSupport for [RFC9580](https://www.rfc-editor.org/rfc/rfc9580.html) (\"OpenPGP v6\") [was developed](https://warmwasserwerfer.de/2025/08/28/towards-openpgp-v6-in-pgpainless/) with funding from the [SovereignTechAgency](https://www.sovereign.tech/) through their\n[SovereignTechFund](https://www.sovereign.tech/programs/fund) program. \n[![SovereignTechFund Logo](https://warmwasserwerfer.de/wp-content/uploads/2025/08/ST-Fund-Logo-Default-Black-CMYK-2048x652.png)](https://www.sovereign.tech/programs/fund)\n\nIn 2025, PGPainless was part of and received financial support from the [Github Secure Open Source Fund](https://github.blog/open-source/maintainers/securing-the-supply-chain-at-scale-starting-with-71-important-open-source-projects/) program.\n\nBig thank you also to those who decided to support the work through individual donations!  \nNotably @msfjarvis\n\nYou make my day!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpgpainless%2Fpgpainless","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpgpainless%2Fpgpainless","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpgpainless%2Fpgpainless/lists"}