Giter VIP home page Giter VIP logo

Comments (9)

ftbarata avatar ftbarata commented on June 14, 2024

An important update:

                            except pkcs11.exceptions.NoSuchKey:
                                cert2 = x509.load_pem_x509_certificate(pem.armor('CERTIFICATE', der_bytes),default_backend())
                                pubdata = cert2.public_key().public_bytes(cryptography.hazmat.primitives.serialization.Encoding.DER,cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo)
                                # pub = pem.armor('RSA PUBLIC KEY', pubdata)
                                pub = pubdata

and in TbsCertificate:

'public_key': RSAPublicKey.load(pub),

It works but when it is parsed by https://redkestrel.co.uk/products/decoder/, there is a problem reading public key:

Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            Unable to load Public Key
140164712199936:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:tasn_dec.c:1197:
140164712199936:error:0D06C03A:asn1 encoding routines:ASN1_D2I_EX_PRIMITIVE:nested asn1 error:tasn_dec.c:765:
140164712199936:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:tasn_dec.c:697:Field=n, Type=RSA
140164712199936:error:0408B004:rsa routines:RSA_PUB_DECODE:RSA lib:rsa_ameth.c:99:
140164712199936:error:0B07707D:x509 certificate routines:X509_PUBKEY_get:public key decode error:x_pubkey.c:154:

from python-pkcs11.

danni avatar danni commented on June 14, 2024

What problem are you trying to solve? If your problem is extracting the public key, extracting it from the X.509 certificate is one option.

You've got a bit of a mixture of mechanisms here. For extracting the public key from an X.509 certificate you can see the function decode_x509_public_key which returns back the template to create a public key option in your HSM.

The key is DER-encoded inside the certificate, so if you want the structured key data, you need to decode it again. You then need to re-encode it to use in the certificate. Avoid PEM except at the input/output, only deal in DER and unencoded data in your code.

I'm not sure why you're replacing public keys in a certificate, but building certificates from scratch is test_self_sign_certificate. This is generic code, totally uncoupled from python-pkcs#11 except for encoding the key to DER and signing the result.

The line RSAPublicKey.load(encode_rsa_public_key(pub)), is encoding a python-pkcs11 PublicKey and encoding it into PKCS#1 DER format (the format required by X.509). And then unloading it back into the representation format of asn1crypto.

You can pass a DER-encoded string from any library, so long as you're encoding the right object. SubjectPublicKeyInfo is the wrong object. You want to pass the object type that matches the AlgorithmIdentifier. See RFC5280. This is the RSAPublicKey object.

Hope this helps.

from python-pkcs11.

ftbarata avatar ftbarata commented on June 14, 2024

Hi @danni , thank you so much for helping me.

The problem I'm trying to solve is: some USB tokens don't expose or don't have public key object(at least not for pkcs11 api). So in this case I can't read pubkey by using python-pkcs11 session.get_key or session.get_objects.
I built this code thanks to both of you and the wbond(asn1crypto author)
Since I'm not an expert in cryptography, some specific pieces of code you two gave me almost literaly.

After this below:

certificate = next(session.get_objects({Attribute.CLASS: pkcs11.constants.ObjectClass.CERTIFICATE}))
der_bytes = certificate[Attribute.VALUE]
pem_bytes = pem.armor('CERTIFICATE', der_bytes)

You or he gave me this code below:

cert2 = x509.load_pem_x509_certificate(pem_bytes,default_backend())
pubdata =  cert2.public_key().public_bytes(cryptography.hazmat.primitives.serialization.Encoding.DER,cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo)

Because the case where it's not possible to get public key from token.

What I need to do is change these lines above so when submiting to https://redkestrel.co.uk/products/decoder/ (or other decoders), the public key information appears like this below:
(Download this: http://valida.sopagomeia.com.br:65400/downloadcertificado/PjKaGaUy and submit into https://redkestrel.co.uk/products/decoder/)

Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:89:e0:e2:b6:ab:39:0d:a0:ce:5e:e9:37:82:6d:
                    b6:f0:13:06:6a:a3:52:11:6c:51:1e:82:8d:4f:1c:
                    0c:1b:ed:21:e4:94:dc:e1:f8:97:74:cd:57:2c:a0:
                    c8:76:8b:c6:42:e0:35:ee:19:e2:04:f4:32:75:2b:
                    25:f7:36:6c:7b:90:c0:91:21:65:25:5d:9e:fb:ce:
                    b3:bb:15:1b:d6:12:34:50:e7:bf:13:c1:4c:45:ad:
                    b2:9e:58:59:ed:c3:39:78:0c:2c:96:f7:a0:36:1d:
                    b9:64:2e:04:25:fb:5e:bd:b0:a9:81:52:55:56:b3:
                    b4:c2:42:f0:28:7e:91:44:f9:81:d8:63:72:68:95:
                    bf:3b:71:38:a6:aa:ae:e5:04:7b:30:5a:f3:b5:33:
                    5b:88:3c:74:35:e4:6b:85:9f:35:54:c0:e1:00:fc:
                    59:5f:91:5e:b3:6c:c8:70:29:8e:3f:a5:c5:68:30:
                    99:4f:a9:6a:09:d2:28:a2:d7:a0:c3:1a:8c:0f:30:
                    d5:73:31:39:52:21:92:4e:9e:20:29:cc:bf:b0:3a:
                    f9:1d:f5:37:9a:a8:59:30:db:19:fa:fe:1d:bc:6a:
                    fb:58:6b:78:90:02:ac:ca:06:6c:2b:b3:a4:2a:c5:
                    54:48:80:8e:e1:5b:e1:0e:39:e9:e0:8c:48:6d:32:
                    af:91
                Exponent: 65537 (0x10001)

Instead of

Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            Unable to load Public Key
140164712199936:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:tasn_dec.c:1197:
140164712199936:error:0D06C03A:asn1 encoding routines:ASN1_D2I_EX_PRIMITIVE:nested asn1 error:tasn_dec.c:765:
140164712199936:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:tasn_dec.c:697:Field=n, Type=RSA
140164712199936:error:0408B004:rsa routines:RSA_PUB_DECODE:RSA lib:rsa_ameth.c:99:
140164712199936:error:0B07707D:x509 certificate routines:X509_PUBKEY_get:public key decode error:x_pubkey.c:154:

I don't have idea why it happens, since I'm not an expert like you and he. I just want to fix it.

What I understand is that the https://github.com/danni/python-pkcs11/blob/master/tests/test_x509.py#L167 generate key pairs for testing and the format of the keys is format ready to be used in TbsCertificate.

I didn't understand you said about SubjectPublicKeyInfo from RFC5280 because what the online decoders show is exactly public key info, right?

Taking the opportunity, I'd like if I understood correctly the concept of attribute certificate: When I create a certificate with some non default attributes, by using extensions, it's called attribute certificate, and you call it building from scratch. After building the TbsCertificate, when it is signed using pkcs11 token, the fresh new signed certificate has the token's public key and informations like algorithm used to make the hash, and the hash itself, besides other things. So, the element that securely binds the newly signed attribute certificate to the token is the token's public key, and it makes the chain of trust, because it works recursively (the token has the public key from the CA that issued it). Is these concepts are correct?

Finally, if you don't mind, could you give me the changes of this bit of code, so I can test and give you a feedback?

from python-pkcs11.

danni avatar danni commented on June 14, 2024

I'm not just going to tell you changes to a bit of code I can't follow. You need to understand the cryptography you're using, else you're likely to make a dangerous mistake. I'm still confused what you're trying to do. You want to extract the public key from the X.509 certificate and then put it back into an X.509 certificate? Or do you want to extract the public key to do cryptography?

Here's an example of using a public key from the device outside the device:

        pub = self.session.get_key(key_type=KeyType.RSA,
                                   object_class=ObjectClass.PUBLIC_KEY)

        # Convert from PKCS#11 attributes to DER-encoded PKCS#1 format
        pub = encode_rsa_public_key(pub)

        from oscrypto.asymmetric import load_public_key, rsa_pkcs1v15_encrypt

        # Convert from DER-encoded PKCS#1 format to oscrypto internal format
        pub = load_public_key(pub)
        crypttext = rsa_pkcs1v15_encrypt(pub, b'Data to encrypt')

        priv = self.session.get_key(key_type=KeyType.RSA,
                                    object_class=ObjectClass.PRIVATE_KEY)

        plaintext = priv.decrypt(crypttext, mechanism=Mechanism.RSA_PKCS)

There's also a load_certificate method that oscrypto can use with methods that take a PublicKey, e.g. rsa_pkcs1v15_encrypt.

# Retrieve a PKCS#11 Certificate
cert = next(session.get_objects({Attribute.CLASS: pkcs11.constants.ObjectClass.CERTIFICATE}))
# Access the DER-encoded version of this certificate
cert = cert[Attribute.VALUE]
# Load this into oscrypto internal format, this can be used for public key cryptography in oscrypto
cert = load_certificate(cert)

You can use any crypto library you like. The docs include how to load certificates e.g. in OpenSSL.

When building X.509 certificates, you need to follow the form of the certificate. ASN.1 is like MsgPack or Protocol Buffers. It stores objects of data, but it doesn't define the schema. These are defined in standards such as X.509.

ASN.1 allows for variant types, which is where the type of a field is variant based on something else. For SubjectPublicKeyInfo there are two fields: AlgorithmIdentifier and the ASN.1 encoded key, encoded in the form specified by AlgorithmIdentifier. Remember that different keys types have different information to be encoded.

When tools such as openssl validate read a certificate they read the AlgorithmIdentifier and then choose the correct decoder for the key itself, e.g. RSAPublicKey. In your code you've passed in SubjectPublicKeyInfo, not RSAPublicKey and so it can't be decoded.

from python-pkcs11.

ftbarata avatar ftbarata commented on June 14, 2024

Hi @danni , now I understood. I am passing in the SubjectPublicKeyInfo instead of RSAPublicKey. In your example you consider that you can get public key object from the external device, but as I commented before, in some usb tokens it's not possible. So I'm trying to get RSAPublicKey in any other way. That's all.

You've asked:
"You want to extract the public key from the X.509 certificate and then put it back into an X.509 certificate? Or do you want to extract the public key to do cryptography?"
I want to extract public key from the USB Token X.509 certificate to pass in to the TBS Certificate Builder, which will be the fresh new attribute certificate, signed by the usb token. That's all.

You did not commented about my conceptual question... If you don't mind, I'd appreciate.

Thanks again.

from python-pkcs11.

danni avatar danni commented on June 14, 2024

Okay so you want to create a new self-signed certificate? Or you want to create a new certificate with your certificate as the signer?

from python-pkcs11.

ftbarata avatar ftbarata commented on June 14, 2024

I want to create a new certificate with my usb token certificate as signer. I'm trying hard to fix the code by using oscrypto functions.

I tried many ways, the last one is:

certificate = next(session.get_objects({Attribute.CLASS: pkcs11.constants.ObjectClass.CERTIFICATE}))
der_bytes = certificate[Attribute.VALUE]
oscrypto_cert = load_certificate(der_bytes)
pub = encode_rsa_public_key(oscrypto_cert.public_key)

But encode_rsa_public_key expects an RSA public key, and I'm passing oscrypto assymetric PublicKey object.
I didn't find a way to encode oscrypto assymetric PublicKey into DER bytes. I'm still looking for how to do it...

from python-pkcs11.

ftbarata avatar ftbarata commented on June 14, 2024

I made it works!
See:

cert2 = x509.load_pem_x509_certificate(pem_bytes,default_backend())
pub_bytes = cert2.public_key().public_bytes(cryptography.hazmat.primitives.serialization.Encoding.DER,cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo)
subject_pub_key_info = parse_public(pub_bytes)

In TbsCertificate:

'subject_public_key_info':subject_pub_key_info

it worked, but I still would like to know how to encode oscrypto assymetric PublicKey into DER bytes...

from python-pkcs11.

danni avatar danni commented on June 14, 2024

If you want to create a new certificate from scratch with its own key and you as the signer, then you want to make a new public key. And then set the issuer as your existing certificate and sign the result with your private key. Have a look at the certificate signing tests in python-pkcs11, e.g. this one. However instead of signing your own certificate, you want to sign someone else's certificate. The basics are the same, you'll just need to create an second keypair (each certificate has its own keypair) and set your first key as the issuer and sign it.

Or if you're signing someone else's certificate, you take a CSR they created, and turn that into a certificate with you as the issuer and sign that, and create no extra keypairs. You should be able to use the CSR and X.509 parsing and validation in OpenSSL as a reference point. Again have a look at how the tests call OpenSSL to validate things.

None of this is related to python-pkcs11, you should consult the manual for the ASN.1/X.509 library of your choice. You could consider just using OpenSSL + its PKCS#11 engine, which is the canonical representation.

from python-pkcs11.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.