ssl.SSLError: [SSL] PEM lib (_ssl.c:3837) - python-3.x

Trying to connect to a server through TLS/SSL connection.
I have searched on StackOverflow but could not find the answer
also to make sure certfile & private key matches
I have checked
https://www.sslshopper.com/certificate-key-matcher.html
and it gives me
The certificate and private key match!
Certificate Hash:
3fe39d1c76d2802002741d0660dea5d7ffb6e170b5fdxxxxxxxxxx
Key Hash:
3fe39d1c76d2802002741d0660dea5d7ffb6e170b5fdxxxxxxxxxx
I tried .crt & .pem & did not work
the error
context.load_cert_chain(certfile=client_cert, keyfile=clients_key,
password=None)
ssl.SSLError: [SSL] PEM lib (_ssl.c:3837)
code:-
def tlstest():
hostAddress = 'x'
hostPort = xxxx
serverHostName = 'x.com'
client_cert = 'D:\ssl\client.pem'
clients_key = 'D:\ssl\clientKey.pem'
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.load_cert_chain(certfile=client_cert, keyfile=clients_key,
password=None)
context.verify_mode = ssl.CERT_REQUIRED

Related

Connecting to Neptune using aiogremlin

I am trying to connect to AWS Neptune using aiogremlin but keep getting SSL certificate errors. I tried using 3 different certificates downloaded from Amazon Trust Repository but none of them work. With AmazonRootCA1.pem and SFSRootCAG2.pem I keep getting File Not Found error and with SFSRootCAG2.cer I get ssl_context.load_cert_chain(ssl.SSLError: [SSL] PEM lib (_ssl.c:4046).
Here is the snippet which I am using to interact with Neptune.
import asyncio
from aiogremlin import DriverRemoteConnection, Graph
from .constants import NEPTUNE_ENDPOINT, CERT_DIR
async def go():
remote_connection = await DriverRemoteConnection.open(f'https://{NEPTUNE_ENDPOINT}:8182/gremlin', 'g',
ssl_certfile=CERT_DIR+'SFSRootCAG2.cer')
g = Graph().traversal().withRemote(remote_connection)
vertices = await g.V().toList()
await remote_connection.close()
return vertices
print(asyncio.get_event_loop().run_until_complete(go()))
Having trouble figuring out if I am using the wrong certificate file or doing something else that is wrong.
I got that exact same error (down to the line 4046 in ssl.c) when I converted my keystore to pem file without the certificate section.
I converted it over again without the '-nocerts' flag and the I got both section in the file like this:
Bag Attributes
friendlyName: mykey
localKeyID: ...
Key Attributes: <No Attributes>
-----BEGIN PRIVATE KEY-----
... [magic key details] ...
-----END PRIVATE KEY-----
Bag Attributes
friendlyName: mykey
localKeyID: ...
subject=C = NO, O = ..., CN = Server Administrator
issuer=C = NO, O = ..., CN = Server Administrator
-----BEGIN CERTIFICATE-----
... [magic key details] ...
-----END CERTIFICATE-----
I also created a new certificate like this that worked without trouble:
# openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout cert.pem

crypto.load_certificate / Get public key encryption

How is it possible from crypto.load_certificate to get the public key encryption ? (for example "RSA (2048 Bits").
I can get the public key easily as below :
from OpenSSL import crypto
cert = crypto.load_certificate(crypto.FILETYPE_PEM, open("certificate.crt")).read()
pubKey = cert.get_pubkey()
But I couldn't find anything in the documentation concerning the encryption. Any ideas?
Actually it is really simple :
from OpenSSL import crypto
cert = crypto.load_certificate(crypto.FILETYPE_PEM, open("certificate.crt")).read()
pubKey = cert.get_pubkey()
keySize = pubKey.bits()
if pubKey.type() == crypto.TYPE_RSA:
keyType = 'RSA'
elif pubKey.type() == crypto.TYPE_DSA:
keyType = 'DSA'
print(keyType + "-" + str(keySize))

Access Denied Signed URL Python3 using cloud front

I am trying to create signed urls for my s3 bucket to which only select people will have access to until the time expires.
I am not able to find the issue in my code. Please help
import boto
from boto.cloudfront import CloudFrontConnection
from boto.cloudfront.distribution import Distribution
import base64
import json
import rsa
import time
def lambda_handler(event, context):
url = "https://notYourUrl.com/example.html"
expires = int(time.time() + 36000)
pem = """-----BEGIN RSA PRIVATE KEY-----
myKey
-----END RSA PRIVATE KEY-----"""
Cloudfront console
key_pair_id = 'myKey'
policy = {
"Statement": [
{
"Resource":url,
"Condition":{
"DateLessThan":{"AWS:EpochTime":expires},
}
}
]
}
policy = json.dumps(policy)
private_key = rsa.PrivateKey.load_pkcs1(pem)
policy = policy.encode("utf-8")
signed = rsa.sign(policy, private_key, 'SHA-1')
policy = base64.b64encode(policy)
policy = policy.decode("utf-8")
signature = base64.urlsafe_b64encode(signed)
signature = signature.decode("utf-8")
policy = policy.replace("+", "-")
policy = policy.replace("=", "_")
policy = policy.replace("/", "~")
signature = signature.replace("+", "-")
signature = signature.replace("=", "_")
signature = signature.replace("/", "~")
print("%s?Expires=%s&Signature=%s&Key-Pair-Id=%s" % (url,expires, signature, key_pair_id))
When I test the file on lambda I am able to produce and print a URL but when I access the URL I receive an access denied error message from the XML file.
I am not sure what I am doing wrong at this point. To test if I am able to generated any SignedUrl I created a node.js lambda in which I am successfully able to generate the URL and even access my page.
<Error>
<Code>AccessDenied</Code>
<Message>Access denied</Message>
</Error>
After many failed tries to make my code work I decided to go with a different approach and used node.js to fullfill my needs. The code below works perfectly and I am able to generate signed url's
For now I used a hardcoded time value to test my code and will later on work on getting that dynamically using datetime.
var AWS = require('aws-sdk');
var keyPairId = 'myKeyPairId';
var privateKey = '-----BEGIN RSA PRIVATE KEY-----' + '\n' +
'-----END RSA PRIVATE KEY-----';
var signer = new AWS.CloudFront.Signer(keyPairId, privateKey);
exports.handler = function(event, context) {
var options = {url: "https://notYourUrl.com/example.html", expires: 1621987200, 'Content-Type': 'text/html'};
//console.log(options);
const cookies = signer.getSignedCookie(options);
const url = signer.getSignedUrl(options);
console.log("Printing URL "+url);
console.log(cookies);
};

TLS/SSL socket python server

I am trying to build a simple HTTPS server with Python3 using the socket and ssl modules.
I have a self signed certificate and a private key files generated by OpenSSL and I tried to use them with the ssl module but every time I try, I get a "ssl.SSLError: [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:1076)" error.
My code is
import socket
import ssl
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
context.load_cert_chain(certfile='cert.pem', keyfile='my_key.key')
context.verify_mode = ssl.CERT_NONE
sock = socket.socket()
sock.bind(('', 443))
sock.listen(5)
while True:
new_conn, addr = sock.accept()
ssl_conn = context.wrap_socket(new_conn, server_side=True)
print(ssl_conn.recv(1024).decode()) # this is where i get the error
The error I get is:
File "C:\AllInOne\PortableApps\Python374\lib\ssl.py", line 1139, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:1076)
Does anyone know why this happens or how to fix it?
Generate server.pem with the following command:
mkdir .ssh
openssl req -new -x509 -keyout .ssh/key.pem -out .ssh/cert.pem -days 365 -nodes
run as follows:
python3 simple-https-server.py
Then in your browser, visit:
https://localhost:4443
Here is the code:
import http.server
from http.server import HTTPServer, BaseHTTPRequestHandler, SimpleHTTPRequestHandler
import ssl
import sys
# This class will handles any incoming request from the browser
class myHandler(BaseHTTPRequestHandler):
# Handler for the GET requests
def do_GET(self):
print(self.requestline)
# print(self.rfile.read(content_length))
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
# Send the html message
self.wfile.write("Hello World !".encode())
return
try:
separator = "-" * 80
server_address = ("", 4443)
# server_address = ('localhost', 4443)
httpd = http.server.HTTPServer(server_address, myHandler)
# httpd = http.server.HTTPServer(server_address, http.server.SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket(
httpd.socket,
server_side=True,
certfile=".ssh/cert.pem",
keyfile=".ssh/key.pem",
ssl_version=ssl.PROTOCOL_TLS,
)
print(separator)
print("Server running on https://localhost:4443")
print(separator)
# Wait forever for incoming htto requests
httpd.serve_forever()
except KeyboardInterrupt:
print("^C received, shutting down the web server")
server.socket.close()
ssl.SSLError: [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:1076)
The client signals your server that it is does not trust your certificate. Which is expected since this is not a certificate issued by a trusted CA and you did not make the client explicit trust this certificate. If the client would not complain it would be insecure since every man in the middle could just use a fake certificate to identify itself as a trusted server.

ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)

I'm currently working on python to QlikSense server connection using websocket-client. for authentication, I have used certificates which are generated by Qlik sense server.
Even I followed the same logic of code mentioned at this link, but still getting an error.
from websocket import create_connection
def conn(senseHost, userDirectory, userId, privateKeyPath):
# self.url = "wss://" + senseHost + ":4747/app/" # invalid
url = "wss://" + senseHost + ":4747/app" # valid
ca = open(privateKeyPath + "root.pem").read()
cer = open(privateKeyPath + "client.pem").read()
key = open(privateKeyPath + "client_key.pem").read()
certs = ({"ca": ca,
"cert": cer,
"key": key})
# import pdb
# pdb.set_trace()
# ERROR raised here.
ws = create_connection(url, sslopt=certs,
header={'X-Qlik-User: UserDirectory=%s; UserId=%s' % (userDirectory, userId)})
session = self.ws.recv()
return session
# below code has specific perameters.
c = conn("blablah.com","XYZ","ME","path/to/cert/")
I traced an error using pdb,
-> ws = create_connection(url,sslopt=certs,header={'X-Qlik-User: UserDirectory=%s; UserId=%s' % (userDirectory, userId)})
(Pdb) n
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)
I found a solution after 4 hours of effort.
def conn(senseHost, userDirectory, userId, privateKeyPath):
url = "wss://" + senseHost + ":4747/app" # valid
certs = ({"ca_certs": privateKeyPath + "root.pem",
"certfile": privateKeyPath + "client.pem",
"keyfile": privateKeyPath + "client_key.pem",
"cert_reqs":ssl.CERT_REQUIRED,
"server_side": False
})
ssl.match_hostname = lambda cert, hostname: True
ws = create_connection(url, sslopt=certs,
header={'X-Qlik-User: UserDirectory=%s; UserId=%s'% (userDirectory, userId)})

Resources