I used following command to get cert & key from a pks file.
openssl pkcs12 -in ../my.pfx -nocerts -out my.key
openssl pkcs12 -in ~/my.pfx -clcerts -nokeys -out cert.pem
However I keep getting error. I suspect my.key is not correct. How to generate the correct key and cert to feed signxml? I use python3.5 on Ubuntu 16.04. Thank you in advance!
File "/home/ubuntu/.local/lib/python3.5/site-packages/signxml/__init__.py", line 362, in sign
key = load_pem_private_key(key, password=passphrase, backend=default_backend())
File "/home/ubuntu/.local/lib/python3.5/site-packages/cryptography/hazmat/primitives/serialization/base.py", line 16, in load_pem_private_key
return backend.load_pem_private_key(data, password)
File "/home/ubuntu/.local/lib/python3.5/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1025, in load_pem_private_key
password,
File "/home/ubuntu/.local/lib/python3.5/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1218, in _load_key
mem_bio = self._bytes_to_bio(data)
File "/home/ubuntu/.local/lib/python3.5/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 454, in _bytes_to_bio
data_ptr = self._ffi.from_buffer(data)
TypeError: from_buffer() cannot return the address of a unicode object
The sample code from xml page:
cert = open("example.pem").read()
key = open("example.key").read()
root = ElementTree.fromstring(data_to_sign)
signed_root = XMLSigner().sign(root, key=key, cert=cert)
verified_data = XMLVerifier().verify(signed_root).signed_xml
I guess it is Python2 vs Python3 thing. All I needed is
key = open("example.key").read().encode('ascii')
Related
I am using the python 3.8 client example on my Modbus application, but I get an error like this:
self._sock = context.wrap_socket(self._sock, server_hostname=self._host)
File "/usr/lib/python3.8/ssl.py", line 500, in wrap_socket
return self.sslsocket_class._create(
File "/usr/lib/python3.8/ssl.py", line 1040, in _create
self.do_handshake()
File "/usr/lib/python3.8/ssl.py", line 1309, in do_handshake
self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: EE certificate key too weak (_ssl.c:1131)
I added the connection codes:
def _do_open(self):
"""Connect to the Modbus slave"""
if self._sock:
self._sock.close()
self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_timeout(self.get_timeout())
self._sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
call_hooks("modbus_tcp.TcpMaster.before_connect", (self, ))
context = SSLContext(ssl.PROTOCOL_TLS_CLIENT)
# context.options |= ssl.OP_NO_SSLv3
context.options |= ssl.OP_NO_TLSv1
# context.options |= ssl.OP_NO_TLSv1_1
context.load_verify_locations('cert.pem')
context.check_hostname = False
# context.verify_mode = ssl.CERT_NONE
# with create_connection((self._host, self._port)) as self._sock:
self._sock.connect((self._host, self._port))
# time.sleep(4)
# print("db:1")
self._sock = context.wrap_socket(self._sock, server_hostname=self._host)
# # print("db:2")
# call_hooks("modbus_tcp.TcpMaster.after_connect", (self, ))
If I added context.verify_mode = ssl.CERT_NONE line for the workaround, it works succefuly but it is not correct way. How Can I solve the problem ?
This is Certificate and Key in Server; (Example key and cert which I found on the github)
const char *privkey = "-----BEGIN PRIVATE KEY-----\n"\
"MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAhD0FKNdH91c8Vis0\n"\
"T7Pli3Grb+BM5xA1V/iNTGer5WSwJlAab6lJ6NNh7R15AXOO7XODOs58ikmEqgWi\n"\
"wacQfwIDAQABAkAG4KeSirPO/OYB80hKtugC2xwX+vn08IZdt2sd5Kxvhzvmp9eM\n"\
"F4QhlQLHOMrk5LkM7FF0G3FgZHlOAZAVbQTtAiEA6SOLWEpnCCEkkCLMmZTcwzV0\n"\
"cX9c7ngnOF/xwIn8IT0CIQCRNJVZ3YcJoXFuOCdUid8qOqdatCDkV8TQNxXxPVSc\n"\
"awIgR1fIMXl7NAKoZK8xeyIRuG7oNj8qWhNMtTSvDyNqk2UCIGgVWi0ldwN3Pviz\n"\
"tbWKcnYxvv5sedtT8pcRtV/MB5drAiBZSqkW9Ha37EObdrctWBvBvHtUp8k9XOy6\n"\
"1X0wxUy5BQ==\n"\
"-----END PRIVATE KEY-----\n";
const char *cert = "-----BEGIN CERTIFICATE-----\n"\
"MIIB2jCCAYSgAwIBAgIIU3U2E0/GMUowDQYJKoZIhvcNAQELBQAwGjEYMBYGA1UE\n"\
"AwwPU3RyYWlnaHQgUm9vdENBMB4XDTIwMTExNTAwMDAwMFoXDTQwMTExNTAwMDAw\n"\
"MFowGjEYMBYGA1UEAwwPU3RyYWlnaHQgU2VydmVyMFwwDQYJKoZIhvcNAQEBBQAD\n"\
"SwAwSAJBAIQ9BSjXR/dXPFYrNE+z5Ytxq2/gTOcQNVf4jUxnq+VksCZQGm+pSejT\n"\
"Ye0deQFzju1zgzrOfIpJhKoFosGnEH8CAwEAAaOBrTCBqjBJBgNVHSMEQjBAgBSD\n"\
"hOKzs+3Mo56OeliOMM0gQZgafKEepBwwGjEYMBYGA1UEAwwPU3RyYWlnaHQgUm9v\n"\
"dENBgghnEtSASbZ0HDAdBgNVHQ4EFgQUGroKNtRTXQ7nxeYSQlZq35oVQDQwDAYD\n"\
"VR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDATAbBgNVHREEFDASggZzZXJ2\n"\
"ZXKCCHN0cmFpZ2h0MA0GCSqGSIb3DQEBCwUAA0EAO02jJwxokR4CeA8DDJqp/9Qk\n"\
"0dim//+cjVTjxqIgUS5ykNW2CAIRuP5rVyzNv6U02F0q92Vs/754/ep+TyT70w==\n"\
"-----END CERTIFICATE-----\n";
The output from openssl x509 -text -in cert.pem on your certificate shows:
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (512 bit)
Modulus:
00:84:3d:05:28:d7:47:f7:57:3c:56:2b:34:4f:b3:
512 bit RSA is terrible weak since years. That's what the program is complaining about. You need to create the certificate with a stronger key, like at least 2048 bit RSA.
Most of the answer I've seen did not work for me or was give an unacceptable solution.
The FUTURE policy, it will cause issues. Even if you do the keys at 3072, your fix one item but many other components are failing as well.
e.g.: Git, yum, curl , php ldap...
You don't need to go back to DEFAULT, it's so furstrating when the answer is to go to the weaker and easy way setting, kinda defeat the purpose of securing, this may not be the strongest setting, but still doesn't use the weak crypt while still allowing for lower keys at 2048. prevent error like "too weak".
If 2048 is to low your you. then this is not your answer and you will have to deal with all the sub components. but if you just want to pass the CIS 2 compliance scan. then this does pass for me and this solution also work with the other compenents.
Try:
Step 1: cd /usr/share/crypto-policies/policies
Step 2: sed 's/= 3072/= 2048/g' /usr/share/crypto- policies/policies/FUTURE.pol > FUTURE2048.pol
Step 3: chmod 644 FUTURE2048.pol
Step 4: update-crypto-policies --set FUTURE2048
Step 5: reboot.
This give you all the setting from FUTURE to eliminate weak crypto but still allow for 2048 keys.
I followed this url to create a X509 certificate. And the code is:
from OpenSSL import crypto, SSL
from socket import gethostname
from pprint import pprint
from time import gmtime, mktime
CERT_FILE = "selfsigned.crt"
KEY_FILE = "private.key"
def create_self_signed_cert():
# create a key pair
k = crypto.PKey()
k.generate_key(crypto.TYPE_<wbr>RSA, 1024)
# create a self-signed cert
cert = crypto.X509()
cert.get_subject().C = "UK"
cert.get_subject().ST = "London"
cert.get_subject().L = "London"
cert.get_subject().O = "Dummy Company Ltd"
cert.get_subject().OU = "Dummy Company Ltd"
cert.get_subject().CN = gethostname()
cert.set_serial_number(1000)
cert.gmtime_adj_notBefore(0)
cert.gmtime_adj_notAfter(10*<wbr>365*24*60*60)
cert.set_issuer(cert.get_<wbr>subject())
cert.set_pubkey(k)
cert.sign(k, 'sha1')
open(CERT_FILE, "wt").write(
crypto.dump_certificate(<wbr>crypto.FILETYPE_PEM, cert))
open(KEY_FILE, "wt").write(
crypto.dump_privatekey(crypto.<wbr>FILETYPE_PEM, k))
create_self_signed_cert()
But there is something wrong with the code when I run it. Could someone tell me what the meaning of <wbr>? There is a SyntaxError in cert.gmtime_adj_notAfter(10*<wbr>365*24*60*60). Thx.
A version which works with python3
from OpenSSL import crypto, SSL
def cert_gen(
emailAddress="emailAddress",
commonName="commonName",
countryName="NT",
localityName="localityName",
stateOrProvinceName="stateOrProvinceName",
organizationName="organizationName",
organizationUnitName="organizationUnitName",
serialNumber=0,
validityStartInSeconds=0,
validityEndInSeconds=10*365*24*60*60,
KEY_FILE = "private.key",
CERT_FILE="selfsigned.crt"):
#can look at generated file using openssl:
#openssl x509 -inform pem -in selfsigned.crt -noout -text
# create a key pair
k = crypto.PKey()
k.generate_key(crypto.TYPE_RSA, 4096)
# create a self-signed cert
cert = crypto.X509()
cert.get_subject().C = countryName
cert.get_subject().ST = stateOrProvinceName
cert.get_subject().L = localityName
cert.get_subject().O = organizationName
cert.get_subject().OU = organizationUnitName
cert.get_subject().CN = commonName
cert.get_subject().emailAddress = emailAddress
cert.set_serial_number(serialNumber)
cert.gmtime_adj_notBefore(0)
cert.gmtime_adj_notAfter(validityEndInSeconds)
cert.set_issuer(cert.get_subject())
cert.set_pubkey(k)
cert.sign(k, 'sha512')
with open(CERT_FILE, "wt") as f:
f.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode("utf-8"))
with open(KEY_FILE, "wt") as f:
f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, k).decode("utf-8"))
cert_gen()
Just remove <wbr>. So stupid I am.
This is a really useful question; as the referenced link is now dead; and this is one of the first results for searching for "python create ssl certificate".
I would add to it though, that "open(xxx, "wt").write()" is asking for problems later. By not explicitly closing the file, you may find that the garbage collector hasn't run when you try to actually use the file - resulting in a failure.
it's better to use:
with open(xxx, "w") as f:
f.write()
which will ensure that the file is closed when you're done.
I would like to do some SSL certificate conversions using python, specifically between:
PEM <--> PFX
PEM <--> P7B
I already have a solution for PEM <--> DER.
Namely:
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.x509 import (
load_der_x509_certificate,
load_pem_x509_certificate,
)
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
cert = form.cleaned_data.get('file')
der_file = pem_to_der(cert)
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
cert = form.cleaned_data.get('file')
pem_file = der_to_pem(cert)
def pem_to_der(cert):
try:
cert_to_der = load_pem_x509_certificate(cert.read(),
default_backend())
except ValueError:
return False
return cert_to_der.public_bytes(serialization.Encoding.DER)
def der_to_pem(cert):
try:
cert_to_der = load_der_x509_certificate(cert.read(),
default_backend())
except ValueError:
return False
return cert_to_der.public_bytes(serialization.Encoding.PEM)
I do have a solution using subprocess.call, as in:
def pem_to_pfx(private_key_path, cert_path, name, passwd):
return subprocess.call("openssl pkcs12 -export -out " + "tmp/"
+ name + ".pfx" + " -password pass:" + passwd + " -inkey "
+ private_key_path + " -in " + cert_path, shell=True)
but I would prefer to avoid this.
Anybody know of a way to do these conversions using the python module cryptography?
cryptography does not currently support serialization to PKCS12/PFX or PKCS7 (although it can parse PKCS12). The project determines development priorities via user reports with concrete use cases so please file an issue!
As a stopgap you can produce PKCS12 using pyOpenSSL (which uses cryptography's bindings), but we'd prefer to build a good API that you can directly use without an additional dependency.
I have a strange case when I try to do encryption with OpenSSL
Details:
I try to encrypt file with "Hello World!"
Password (String): "testtesttesttest"
Password (HEX): 74657374746573747465737474657374
Terminal commands to encrypt file:
For plain text password
openssl aes-128-cbc -e -a -nosalt -iv [some vector] -k [password] -in [input file] -out [output file]
openssl aes-128-cbc -e -a -nosalt -iv [some vector] -pass pass:[password] -in [input file] -out [output file]
For password in HEX format
openssl aes-128-cbc -e -a -nosalt -iv [some vector] -K [HEX password] -in [input file] -out [output file]
So the only difference in commands is that one uses plain text password while another uses the same password but in HEX form. So in my opinion the result of encryption should be the same. But the Base64 output is actually different.
Maybe somebody know and can hint what could be the case here?
Another case that now I develop a small application that encrypts files on Blackberry phone and I would that it would be compatible with other encryption software like OpenSSL that are available on PC. So the Base64 output of my application is not the same as OpenSSL produces with the given password.
The sample code looks like this:
String testKey = "testtesttesttest"; (example)
byte[] aesKeyAsBytes = testKey.getBytes();
AESKey aesKey = new AESKey(aesKeyAsBytes);
AESEncryptorEngine engine = new AESEncryptorEngine(aesKey);
CBCEncryptorEngine cengine=new CBCEncryptorEngine(engine, new InitializationVector(_initVector));
PKCS5FormatterEngine fengine = new PKCS5FormatterEngine(cengine);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
BlockEncryptor cryptoStream = new BlockEncryptor(fengine, outputStream);
cryptoStream.write(plainText, 0, numOfPlainTextBytes);
cryptoStream.close();
byte[] cipherText = outputStream.toByteArray();
outputStream.close();
return cipherText;
I used the following inputs as test data for this scenario:
Key (Hex): 01010101010101010101010101010101
IV (Hex): 02020202020202020202020202020202
Plaintext: Hello, World!
Using the above inputs with the following command in OpenSSL:
openssl aes-128-cbc -K 01010101010101010101010101010101 -iv 02020202020202020202020202020202 -e -a -in in.txt -out out-openssl.txt
Gave me a result of:
wT6aF/PXrGhxEwyX6mNfXA==
Using the C# System.Security.Cryptography namespace, which has a raw AES implementation that we can test against, I used the following code:
using (AesManaged aes = new AesManaged())
{
aes.KeySize = 128;
aes.Padding = PaddingMode.PKCS7;
aes.Key = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
aes.IV = new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 };
byte[] plaintext = Encoding.UTF8.GetBytes("Hello, World!");
ICryptoTransform t = aes.CreateEncryptor();
byte[] ciphertext = t.TransformFinalBlock(plaintext, 0, plaintext.Length);
Console.WriteLine(Convert.ToBase64String(ciphertext));
}
To produce the exact same base64 result of:
wT6aF/PXrGhxEwyX6mNfXA==
This demonstrates that the OpenSSL command above is the correct one to use if you wish for the key to be used exactly as provided (e.g. the -K flag with the uppercase K).
As I mentioned in comments, OpenSSL does use a KDF when providing a password as plaintext, as detailed in this answer.
From man page for enc which should be present on any Unixy system (sometimes under a modified section like 1ssl) or current release on the web:
-k password
the password to derive the key from. This is for compatibility with
previous versions of OpenSSL. Superseded by the -pass argument.
-kfile filename
read the password to derive the key from the first line of
filename. This is for compatibility with previous versions of
OpenSSL. Superseded by the -pass argument.
-K key
the actual key to use: this must be represented as a string
comprised only of hex digits. If only the key is specified, the IV ...
Do you see any difference between '(the) password the key is derived from' and 'the actual key'?
PS: since -K does not do key derivation, the arguments related to salt -nosalt -salt -S have no effect on it and are ignored.
I need to put extensions in a certificate like this in the picture, I tried many ways, but I can not.
I'm running:
"#openssl req -new -keyout $nomerepre.key -out $nomerepre.csr -passin pass:$senha -config myconfig.cnf"
"#openssl x509 -req -days 365 -in $nomerepre.csr -CA ca.crt -CAkey ca.key -set_serial 10102014 -out $nomerepre.crt -passin pass:$senha -extfile myconfig.cnf -extensions v3_req"
My configuration file is thus below
myconfigssl.conf
oid_section = OIDs
[ req ]
default_bits = 2048
prompt = no
encrypt_key = no
default_md = sha1
distinguished_name = dn
req_extensions = v3_req
[ OIDs ]
MyOID=2.16.76.1.3.4
[ dn ]
CN = John Smith
emailAddress = john.smith#quovadisglobal.com
O = QuoVadis Group
C = US
[v3_req]
1.2.3.4.5.6.7.8=ASN1:UTF8String:Something
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
#subjectAltName = #alt_names
[alt_names]
MyOID = 00000000111111111112222222222233333333333444444
2.16.76.1.3.4 = 00000000111111111112222222222233333333333444444
Unfortunately the result that this is going:
I don't understand why you got no extensions as shown in EG2Oa.jpg. You should have extension 1.2.3.4.5.6.7.8 there. SubjectAltName is commented so it should not be in the certificate.
I tried using xca which uses OpenSSL 1.0.2d as show in the picture
I used this config
# if it should be a separate extension
2.16.76.1.3.4=ASN1:UTF8String:Some random data
#if it should be a part of subjectAltName
subjectAltName=#subject_alt_section
[subject_alt_section]
otherName=2.16.76.1.3.4;UTF8:Some random data
And I got this certificate
Now some theory. I don't know where this extension should be placed. If it is a separate extension or if it should be a part of SubjectAltName. I don't know if the extension should be an UTF8String or OctetString or a Sequence of something.
If you want a separate extension you can use 2.16.76.1.3.4=ASN1:UTF8String:Some random data as you already tried. More on arbitrary extensions can be found here.
This extension can be part of subjectAltName according to the description of the oid. Definition of otherName can be found in RFC5280 in section 4.2.1.6. If so then this config worked for me
subjectAltName=#subject_alt_section
[subject_alt_section]
otherName=2.16.76.1.3.4;UTF8:Some random data
Using the above mentioned config I've got structure of the certificate as shown in the picture below. ASN1Editor was used to show the structure.