chapeau/kepi/bowler_pub/crypto.py

79 wiersze
1.9 KiB
Python

# crypto.py
#
# Part of kepi, an ActivityPub daemon.
# Copyright (c) 2018-2019 Marnanel Thurman.
# Licensed under the GNU Public License v2.
"""
Various crypto routines, used for signing messages and
verifying other people's signatures.
"""
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA256
from struct import pack
import base64
import hashlib
def base64url_encode(data):
"""
base64-encodes its input, using the modified URL-safe
alphabet given in RFC 4648.
"""
b = base64.b64encode(s=data,
altchars=b'-_')
return str(b, encoding='ASCII')
def bignum_to_bytes(bignum):
temp = bignum
result = []
while temp!=0:
result.append(temp & 0xFF)
temp >>= 8
result.reverse()
return bytes(result)
class Key(object):
"""
An RSA public/private key pair, which can produce
a magic-envelope signature for itself.
I was going to subclass the RSA key object,
but it's hidden away and has an underscore prefix,
so I guess the developers thought that was a bad idea.
So I'm wrapping it, instead.
"""
def __init__(self):
self._rsa_key = RSA.generate(1024)
def private_as_pem(self):
return str(self._rsa_key.exportKey('PEM'),
encoding='ASCII')
def public_as_pem(self):
return str(self._rsa_key.publickey().exportKey('PEM'),
encoding='ASCII')
def modulus(self):
return self._rsa_key.n
def public_exponent(self):
return self._rsa_key.e
def private_exponent(self):
return self._rsa_key.d
def magic_envelope(self):
return 'RSA.{0}.{1}'.format(
base64url_encode(
bignum_to_bytes(
self._rsa_key.n)),
base64url_encode(
bignum_to_bytes(
self._rsa_key.e)),
)