# Pre-shared key-based certificate authority and requestor
This package implements a protocol for certificate issuance that two parties
(a server, the CA -- and a client, the requestor) can use to negotiate the
issuance of certificates valid from the perspective of the CA. The only
prerequisites for a successful certificate issuance are:
1. There is a cleartext communication channel between the two parties.
2. Both parties already have a PSK they both trust (generated, perhaps
with the blindecdh Python module, and then subsequently verified
by both parties).
The purpose of this is to establish enduring trust between server and client.
After successful untampered and verified key exchange between two parties
(the server and the client), both have a shared secret they can use to encrypt
and decrypt traffic. This is useful, but the key is not enough — the modern
goal of communications cryptography is to arrive at mutually authenticated TLS
between the peers, so that the peers can then continue in a fully symmetrically
authenticated manner (e.g. via mTLS or gRPC).
The package contains two main parts:
1. a certificate authority (CA) capable of issuing certificates to authorized
entities,
2. a certificate requestor to negotiate certificate issuance requests with the
certificate authority.
Authentication for certificate issuance is predicated on both sides (the CA
and the requestor) holding a pre-shared key (which can be negotiated via ECDH
using the [blindecdh package](https://github.com/Rudd-O/blindecdh) and then
authorized using the
[shortauthstrings package](https://github.com/Rudd-O/shortauthstrings)).
A set of utility functions and objects are also provided to simplify use of
this package.
Here is some sample code:
```
import os, pskca
client_id = "xxx"
ca_cert, ca_key = pskca.create_certificate_and_key(ca=True)
client_csr, client_key = pskca.create_certificate_signing_request()
psk = os.urandom(32)
C = pskca.CA(ca_cert, ca_key)
C.add_psk(client_id, psk)
R = pskca.Requestor(psk)
payload = R.encrypt_csr(client_csr)
# If you were sending the encrypted payload over the wire, you'd then
# call .to_bytes() on the object resulting from encrypt_csr() call.
_, __, enc_client_cert, enc_cert_chain = C.issue_certificate(client_id, payload)
# If you received enc_client_cert and enc_cert_chain over the wire,
# they'd be bytes, so you'd create the respective objects thus:
# enc_client_cert = pskca.EncryptedClientCertificate(enc_client_cert)
# enc_cert_chain = pskca.EncryptedCertificateChain(enc_cert_chain)
client_cert, enc_cert_chain = R.decrypt_reply(enc_client_cert, enc_cert_chain)
print("Client certificate obtained: %s" % client_cert)
print("Root of trust certificate obtained: %s" % cert_chain)
print("CA certificate should be valid according to root of trust: %s" % ca_cert)
# Client certificate obtained: <Certificate(subject=<Name(CN=projects)>, ...)>
# Root of trust certificate obtained: [<Certificate(subject=<Name(C=XX,...)>...]
# CA certificate should be valid according to root of trust: <Certificate(subject=<Name(C=XX...)>
```
You'll find more developer and implementation documentation in the
[module](https://github.com/Rudd-O/pskca/blob/master/src/pskca/__init__.py).
This package is distributed under the GNU Lesser General Public License v2.1.
For relicensing, contact the package author.
Raw data
{
"_id": null,
"home_page": "https://github.com/Rudd-O/pskca",
"name": "pskca",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "",
"author": "Manuel Amador (Rudd-O)",
"author_email": "rudd-o@rudd-o.com",
"download_url": "https://files.pythonhosted.org/packages/9a/36/a343be4f8784dec243e9956e9e4d6cd6733b4631e83ff70c106a5af0350f/pskca-0.1.11.tar.gz",
"platform": null,
"description": "# Pre-shared key-based certificate authority and requestor\n\nThis package implements a protocol for certificate issuance that two parties\n(a server, the CA -- and a client, the requestor) can use to negotiate the\nissuance of certificates valid from the perspective of the CA. The only\nprerequisites for a successful certificate issuance are:\n\n1. There is a cleartext communication channel between the two parties.\n2. Both parties already have a PSK they both trust (generated, perhaps\n with the blindecdh Python module, and then subsequently verified\n by both parties).\n\nThe purpose of this is to establish enduring trust between server and client.\n\nAfter successful untampered and verified key exchange between two parties\n(the server and the client), both have a shared secret they can use to encrypt\nand decrypt traffic. This is useful, but the key is not enough \u2014 the modern\ngoal of communications cryptography is to arrive at mutually authenticated TLS\nbetween the peers, so that the peers can then continue in a fully symmetrically\nauthenticated manner (e.g. via mTLS or gRPC).\n\nThe package contains two main parts:\n\n1. a certificate authority (CA) capable of issuing certificates to authorized\n entities,\n2. a certificate requestor to negotiate certificate issuance requests with the\n certificate authority.\n\nAuthentication for certificate issuance is predicated on both sides (the CA\nand the requestor) holding a pre-shared key (which can be negotiated via ECDH\nusing the [blindecdh package](https://github.com/Rudd-O/blindecdh) and then\nauthorized using the\n[shortauthstrings package](https://github.com/Rudd-O/shortauthstrings)).\n\nA set of utility functions and objects are also provided to simplify use of\nthis package.\n\nHere is some sample code:\n\n```\nimport os, pskca\n\nclient_id = \"xxx\"\nca_cert, ca_key = pskca.create_certificate_and_key(ca=True)\nclient_csr, client_key = pskca.create_certificate_signing_request()\npsk = os.urandom(32)\n\nC = pskca.CA(ca_cert, ca_key)\nC.add_psk(client_id, psk)\nR = pskca.Requestor(psk)\npayload = R.encrypt_csr(client_csr)\n# If you were sending the encrypted payload over the wire, you'd then\n# call .to_bytes() on the object resulting from encrypt_csr() call.\n_, __, enc_client_cert, enc_cert_chain = C.issue_certificate(client_id, payload)\n\n# If you received enc_client_cert and enc_cert_chain over the wire,\n# they'd be bytes, so you'd create the respective objects thus:\n# enc_client_cert = pskca.EncryptedClientCertificate(enc_client_cert)\n# enc_cert_chain = pskca.EncryptedCertificateChain(enc_cert_chain)\nclient_cert, enc_cert_chain = R.decrypt_reply(enc_client_cert, enc_cert_chain)\n\nprint(\"Client certificate obtained: %s\" % client_cert)\nprint(\"Root of trust certificate obtained: %s\" % cert_chain)\nprint(\"CA certificate should be valid according to root of trust: %s\" % ca_cert)\n\n# Client certificate obtained: <Certificate(subject=<Name(CN=projects)>, ...)>\n# Root of trust certificate obtained: [<Certificate(subject=<Name(C=XX,...)>...]\n# CA certificate should be valid according to root of trust: <Certificate(subject=<Name(C=XX...)>\n```\n\nYou'll find more developer and implementation documentation in the\n[module](https://github.com/Rudd-O/pskca/blob/master/src/pskca/__init__.py).\n\nThis package is distributed under the GNU Lesser General Public License v2.1.\nFor relicensing, contact the package author.\n",
"bugtrack_url": null,
"license": "",
"summary": "A simple implementation of unauthenticated ECDH",
"version": "0.1.11",
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "9a36a343be4f8784dec243e9956e9e4d6cd6733b4631e83ff70c106a5af0350f",
"md5": "d33bedfa5b1d3fbe2286a4df4636b3e7",
"sha256": "50896e0ebd725e5c4730bff82d229c5fe3fc8fecd43dd2c8cf8f71d52b71ace2"
},
"downloads": -1,
"filename": "pskca-0.1.11.tar.gz",
"has_sig": false,
"md5_digest": "d33bedfa5b1d3fbe2286a4df4636b3e7",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 23238,
"upload_time": "2023-02-06T02:43:06",
"upload_time_iso_8601": "2023-02-06T02:43:06.914940Z",
"url": "https://files.pythonhosted.org/packages/9a/36/a343be4f8784dec243e9956e9e4d6cd6733b4631e83ff70c106a5af0350f/pskca-0.1.11.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-02-06 02:43:06",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "Rudd-O",
"github_project": "pskca",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"tox": true,
"lcname": "pskca"
}