Connecting to Neptune using aiogremlin - python-3.x

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

Related

Cryptography.py using encrypt with private key and decrypt with public key

I need to encrypt a string using a private key. Then I want to use the asymmetric public key to decrypt the encrypted string and obtain the original string. I am using cryptography.py which allows the opposite (public for encryption and private for decryption). Is there a method included with this library that would allow me to do this?
Note: I have tried to use the private_key.sign() method and this works for encryption. Reading articles I learned this is not a safe nor 'good' way of encrypting and is only used to verify the key.
I am open to using a different library if I need to. I have done a lot of research on this topic and can not find anything online that works with python. Im open for suggestions, thanks.
I will post my code below, read_public() and read_private() is returning an rsa object from crytopgraphy.py
def encrypt(message):
######### Public (shared) device only #########
message = bytes(message,'utf-8')
private_key = read_private()
encrypted = private_key.encrypt( #use private
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
return encrypted
def decrypt(encrypted):
######### Private device only ##########
#encrypted = bytes(encrypted, 'utf-8')
public_key = read_public()
original_message = public_key.decrypt( #use public
encrypted,
padding.OAEP(
#mask generated function object
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
return original_message
output: Console output
I understand this error message and why it does not work, is there a way to make this work?

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))

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] PEM lib (_ssl.c:3837)

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

Trying to automate certificate generation with python3.cryptography; not having luck

I'm trying to programmatically create client certificates for mosquitto clients to use. Using XCA, I've been able to create a self signed CA, an intermediate, and then a certificate from the intermediate. I've configured mosquitto with the `require_certificate true' option. Using keys exported from XCA, I'm able to use the paho clients for testing:
mosquitto_sub -h ubuntu -p 8765 -t /1/2/3 --cafile ~/CA2/Chain.crt -d --cert ./test1.crt --key ./test1.pem
This works.
Now I'm trying to automate the key generation with a python3 script using the cryptography module.
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography import x509
from cryptography.hazmat.primitives import hashes
from cryptography.x509.oid import NameOID
from pathlib import Path
from datetime import datetime, timezone, timedelta
import uuid
privateKey = rsa.generate_private_key(
public_exponent=65537,
key_size=4096,
backend=default_backend())
with Path('test2.pem').open('wb') as stream:
stream.write(privateKey.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()))
builder = x509.CertificateBuilder()
builder = builder.subject_name(x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, uuid.uuid4().hex),
]))
builder = builder.issuer_name(x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, u'ubuntu'),
]))
builder = builder.not_valid_before(datetime.now(timezone.utc) - timedelta(days=1))
builder = builder.not_valid_after(datetime.now(timezone.utc) + timedelta(days=365*50))
builder = builder.serial_number(x509.random_serial_number())
builder = builder.public_key(privateKey.public_key())
builder = builder.add_extension(
x509.BasicConstraints(ca=False, path_length=None), critical=True,
)
builder = builder.add_extension(
x509.SubjectKeyIdentifier.from_public_key(privateKey.public_key()), critical=False,
)
builder = builder.add_extension(
x509.KeyUsage(digital_signature=True,
content_commitment=False,
key_encipherment=True,
data_encipherment=True,
key_agreement=False,
key_cert_sign=False,
crl_sign=False,
encipher_only=False,
decipher_only=False), critical=False,
)
certificate = builder.sign(
private_key=privateKey, algorithm=hashes.SHA256(),
backend=default_backend()
)
print(certificate)
with Path('test2.crt').open('wb') as stream:
stream.write(certificate.public_bytes(encoding=serialization.Encoding.PEM))
I've used openssl x509 -in certFile.crt -text -noout to compare the XCA variant vs my automated one. They look darn near identical to me. However, the sub doesn't work:
$ mosquitto_sub -h ubuntu -p 8765 -t /1/2/3 --cafile ~/CA2/Chain.crt -d --cert ./cert.crt --key ./key.pem
Client mosqsub|34613-ubuntu sending CONNECT
Error: A TLS error occurred.
The problem as pointed out in another source, was that I was signing the new certificate with the same key as I was generating the certificate from. Like the issue name is to be the same name as the issuing certificate, the signing key should be the private key of that same issuing certificate. Replacing the signing clause with something like:
parentKey = serialization.load_pem_private_key(
Path('path/to/intermediate_key.pem').read_bytes(),
password=None,
backend=default_backend())
certificate = builder.sign(
private_key=parentKey,
algorithm=hashes.SHA256(),
backend=default_backend()
)

Resources