Extract public key from PEM encoded x509 public key certificate - python-3.x

I have been attempting to retrieve the raw public key and place it in an object of type bytearray without success.
from cryptography import x509
from cryptography.hazmat.primitives.serialization import Encoding
from cryptography.hazmat.primitives.serialization import PublicFormat
cert = x509.load_pem_x509_certifcate(pem_encoded_cert)
pk = cert.public_key()
I have been attempting to retrieve the raw public key and place it in an object of type bytearray without success; e.g.
in_buf = bytearray(pk.public_bytes(Encoding.OpenSSH, PublicFormat.OpenSSH))
I cannot find a combination of Encoding and PublicFormat that provides the raw public key bytes; is the above the correct approach or is there a better solution?
Thanks in advance.

Related

No inverse error during encryption (node-rsa)

I am trying to convert https://clover.app.box.com/s/rz18bni3bpmdrc8wc92xm4w8h9grrtty from Java to node.js
I am using the node-rsa package and getting error:0306E06C:bignum routines:BN_mod_inverse:no inverse when trying to encrypt using an imported public key.
According to the clover example, I want to
Parse the Base64 public key string (returned by the CDN). Obtain the modulus and exponent.
Generate an RSA public key using the modulus and exponent values.
Prepend the prefix value to the card number.
Using the public key, encrypt the combined prefix and card number.
Base64 encode the resulting encrypted data into a string.
I was able to get the modulus and exponent, and it matches the result in Java:
modulus: 24130287975021244042702223805688721202041521798556826651085672609155097623636349771918006235309701436638877260677191655500886975872679820355397440672922966114867081224266610192869324297514124544273216940817802300465149818663693299511097403105193694390420041695022375597863889602539348837984499566822859405785094021038882988619692110445776031330831112388738257159574572412058904373392173474311363017975036752132291687352767767085957596076340458420658040735725435536120045045686926201660857778184633632435163609220055250478625974096455522280609375267155256216043291335838965519403970406995613301546002859220118001163241
exponent: 415029
Now I want to create a public key with it, and encrypt a message:
const key = new NodeRSA();
// generate RSA public key using mod and exp values
key.importKey({
n: Buffer.from('24130287975021244042702223805688721202041521798556826651085672609155097623636349771918006235309701436638877260677191655500886975872679820355397440672922966114867081224266610192869324297514124544273216940817802300465149818663693299511097403105193694390420041695022375597863889602539348837984499566822859405785094021038882988619692110445776031330831112388738257159574572412058904373392173474311363017975036752132291687352767767085957596076340458420658040735725435536120045045686926201660857778184633632435163609220055250478625974096455522280609375267155256216043291335838965519403970406995613301546002859220118001163241', 'hex'),
e: Buffer.from('415029', 'hex')
}, 'components-public');
// using public key, encrypt message
// base64 encode encrypted data to string
const encryptedString = key.encrypt(Buffer.from('message', 'hex'), 'base64', 'hex');
However, I am getting the no inverse error mentioned above. It seems to be caused by the modulus. If I change it to something shorter, the error goes away.

how convert a public key from string type to PEM

I have a problem and I want some help.
I need to send a message from sender to receiver, and this message content signed data and public key and other things. note that I use the certificate x509 (the public key is from the certificate). On the receiver side, I must verify the signature of the data ( true or not). So, I use the public key of the sender for verification. But I had a problem, the public key is a string format. and i try to convert it . but unfortunately, i don't found any solution.
this the message that will be send:
data['message'] = data
data['_signature'] = self.sign_data(data)
data['_public_key'] = str ( self.certificate.public_key())
You cannot convert the public key (certificate.public_key()) into string by using str, because this method will return key object.
if you need to encode the public key as PEM string, then you have to do it correctly, by serialization into PEM:
public_pem = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
Then from other side, you could load the PEM key and use it:
from cryptography.hazmat.primitives import serialization
public_key2 = serialization.load_pem_public_key(public_pem, default_backend())

How to create java.security.PublicKey from AsymmetricKeyParameter

Hi I'm trying to write a public key to a PEM file.
org.bouncycastle.openssl.jcajce.JcaPEMWriter seem to be the right tool, but it uses org.bouncycastle.openssl.jcajce.JcaMiscPEMGenerator which expects keys that is an instance of java.security.PublicKey.
Unfortunately, all the rest of the project I'm working on uses AsymmetricKeyParameter for public keys. I checked inside it has everything you would want to know from a public key, including point G and curve order, but it's not compatible with java.security.PublicKey.
Is there a way to use JcaPEMWriter if what I have is instances of AsymmetricKeyParameter? I use ECDSA key by the way.
(I am at first surprised at this because BouncyCastle's JcaPEMWriter isn't compatible with their own class, AsymmetricKeyParameter)
It doesn't look like the JcaPEMWriter can directly handle an AsymmetricKeyParameter object. But it is relatively easy to convert an AsymmetricKeyParameter object to a PublicKey object.
For this BouncyCastle's EC5Util class can be applied which handles the conversion from ECDomainParameters to ECParameterSpec and from BouncyCastle's ECPoint to Java's ECPoint.
The PublicKey object can then be exported as before with the JcaPEMWriter as an X.509/SPKI PEM encoded public key:
// AsymmetricKeyParameter object containing the public EC key
AsymmetricKeyParameter asymmetricKeyParameter = ...
// Convert AsymmetricKeyParameter object to PublicKey object
ECPublicKeyParameters ecPublicKeyParameters = (ECPublicKeyParameters)asymmetricKeyParameter;
ECParameterSpec ecParameterSpec = EC5Util.convertToSpec(ecPublicKeyParameters.getParameters());
ECPoint ecPoint = EC5Util.convertPoint(ecPublicKeyParameters.getQ());
ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(ecPoint, ecParameterSpec);
PublicKey publicKey = KeyFactory.getInstance("EC").generatePublic(ecPublicKeySpec);
// Export PublicKey object with JcaPEMWriter in X.509/SPKI format, PEM encoded
...

get »fingerprint« from rsa key

By using the crypto module, it is easy to create a private/public key Pair in node. But how can I compute the »fingerprint« of a key?
OpenCrypto has something like that:
crypt.getFingerprint(key, options).then(function (fingerprint) {
console.log(fingerprint)
})
What is the equivalent of nodes crypto module for that?
OpenCrypto.getFingerprint exports a public RSA key in the X509 DER format and creates a hash for these data. The same applies to a private RSA key with the difference that the private key is exported in the Pkcs8 DER format. The digest can be specified in the options (default: SHA 512) and also whether the data are returned as buffer or as hexadecimal string (default: hexadecimal string).
In the NodeJS code, keys can be generated with crypto.generateKeyPair, whereby the key format can be specified explicitly. If the keys aren't already in the appropriate formats (X509 DER and Pkcs8 DER) key conversions can be performed to produce the same fingerprints that OpenCrypto.getFingerprint creates. Suitable functions for these operations are crypto.createPublicKey or crypto.createPrivateKey. Finally the hash has to be generated with crypto.createHash.
Update:
The fingerprint is nothing else than a hash value, e.g. with the digest SHA-512 (as in OpenCrypto.getFingerprint):
var fingerprint = crypto.createHash('sha512').update(key).digest('hex'); // Fingerprint (hash) as hexadecimal string
where key is a public or private key in any format (string, Buffer, ...). If the key is given as X509 DER (public) or as PKCS8 DER (private), then the fingerprint matches that of OpenCrypto.getFingerprint.
If the key is in another format, the fingerprint can also be determined in this way. However, if the fingerprint should match the value provided by OpenCrypto.getFingerprint, the key must of course be converted into the formats used by OpenCrypto.getFingerprint before the hash is generated. This conversion isn't very complex, e.g. the conversion of a public PKCS1 PEM key (publicKey) into a X509 DER key (publicKeyDER) including the generation of the hash:
var publicKeyDER = crypto.createPublicKey(publicKey, { type: 'pkcs1', format: 'pem' }).export({ type: 'spki', format: 'der' }); // Convert a public PKCS1 PEM key into a X509 DER key
var fingerprint = crypto.createHash('sha512').update(publicKeyDER).digest('hex'); // Fingerprint (hash) as hexadecimal string
The bottom line is that these are functionally the same operations that are performed in OpenCrypto.getFingerprint. To my knowledge, there is no OpenCrypto.getFingerprint counterpart in the NodeJS crypto module. But with only little effort you can write your own function using the above crypto functions.

Mapping problem of PKCS11 EC public key to BC PKCS10 object

I have created EC key pair in HSM using PKCS11Interop library, and i need to create PKCS10 Certificate request using this keys. For generation of PKCS10 I use BC, and in this situation i need to set public key as a parameter for PKCS10 request.
In BC i need to get public key as ECPublicKeyParameters for putting in PKCS10 object. I do not know how to map PKCS11 public key to ECPublicKeyParameters.
Or may be there is another method for this type mapping?
Thanks in advance!
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.util.PublicKeyFactory;
AsymmetricKeyParameter keyParameters = PublicKeyFactory.createKey(publicKey.getEncoded());
if (keyParameters instanceof ECPublicKeyParameters) {
ECPublicKeyParameters ecPublicKeyParameters = (ECPublicKeyParameters) keyParameters;
}

Resources