I have a python code for Csr and key generation using pyopenssl. I am trying to add an additional attribute, "challenge password" while generating the CSR. Could someone please help on implementing challenge password to the below code?
Additional attribute using openssl look something like this: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []:asdfasdf
import OpenSSL
from OpenSSL.crypto import load_certificate_request, FILETYPE_PEM
def create_csr(common_name, country, state=None, city=None,
organization=None, organizational_unit=None,
email_address=None, san_list=None):
key = OpenSSL.crypto.PKey()
key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048)
req = OpenSSL.crypto.X509Req()
req.get_subject().CN = common_name
if country:
req.get_subject().C = country
if state:
req.get_subject().ST = state
if city:
req.get_subject().L = city
if organization:
req.get_subject().O = organization
if organizational_unit:
req.get_subject().OU = organizational_unit
if email_address:
req.get_subject().emailAddress = email_address
if san_list:
req.add_extensions([
OpenSSL.crypto.X509Extension(
"subjectAltName".encode("utf-8"), False, (", ").join(san_list).encode("utf-8"))])
req.set_pubkey(key)
req.sign(key, 'sha256')
private_key = OpenSSL.crypto.dump_privatekey(
OpenSSL.crypto.FILETYPE_PEM, key)
csr = OpenSSL.crypto.dump_certificate_request(
OpenSSL.crypto.FILETYPE_PEM, req)
private_key = private_key.decode()
csr = csr.decode()
return private_key, csr
```
pyopenssl
does not have appear to have support for this.
You could do it using cryptography
instead, though.
# safe stuff
from cryptography import x509
from cryptography.x509.oid import NameOID, AttributeOID
# land mines, dragons, and dinosaurs with laser guns
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.hashes import SHA256
from cryptography.hazmat.primitives.serialization import Encoding
from cryptography.hazmat.primitives.serialization import NoEncryption
from cryptography.hazmat.primitives.serialization import PrivateFormat
# Standard RSA public exponent, should be a "big enough" low hamming weight prime
# https://en.wikipedia.org/wiki/Coppersmith%27s_attack#Low_public_exponent_attack
RSA_E = 65537
RSA_BITS = 2048
PEM = Encoding.PEM
PKCS8 = PrivateFormat.PKCS8
def create_csr(common_name, country, state=None, city=None,
organization=None, organizational_unit=None,
email_address=None, san_list=None,
password=None, backend=default_backend):
key = rsa.generate_private_key(RSA_E, RSA_BITS, backend())
csrb = x509.CertificateSigningRequestBuilder()
subject = []
def add_subject(oid, value):
if value is not None:
subject.append(x509.NameAttribute(oid, value))
add_subject(NameOID.COMMON_NAME, common_name)
add_subject(NameOID.COUNTRY_NAME, country)
add_subject(NameOID.STATE_OR_PROVINCE_NAME, state)
add_subject(NameOID.LOCALITY_NAME, city)
add_subject(NameOID.ORGANIZATION_NAME, organization)
add_subject(NameOID.ORGANIZATIONAL_UNIT_NAME, organizational_unit)
add_subject(NameOID.EMAIL_ADDRESS, email_address)
csrb = csrb.subject_name(x509.Name(subject))
if san_list is None: san_list = [common_name]
sans = list(map(x509.DNSName, san_list))
csrb = csrb.add_extension(x509.SubjectAlternativeName(sans), critical=False)
# challenge password is included as plaintext in the request
if password is not None:
csrb = csrb.add_attribute(
AttributeOID.CHALLENGE_PASSWORD,
password.encode('utf-8'),
)
req = csrb.sign(key, SHA256())
pem_key = key.private_bytes(PEM, PKCS8, NoEncryption()).decode()
pem_req = req.public_bytes(encoding=PEM).decode()
return pem_key, pem_req