python function for plpython3u

49 Views Asked by At

I have a python function that works perfectly, but I need to pass it to plpython3u (don't ask me why, juniors only obey) python function:

import cryptography.hazmat.primitives.serialization.pkcs12 as pkcs12
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes

pfx_path = 'C:/Users/rodri/OneDrive/Documentos/ApiBradesco/certificados/comeli/123456890.pfx'
pfx_password = b'123456789'  

def load_private_key_and_certificate(pfx_path, pfx_password):
    with open(pfx_path, 'rb') as f:
        pfx_data = f.read()
    
    private_key, certificate, additional_certificates = pkcs12.load_key_and_certificates(
        pfx_data, pfx_password)
    
    private_key_pem = private_key.private_bytes(
        encoding=pkcs12.serialization.Encoding.PEM,
        format=pkcs12.serialization.PrivateFormat.PKCS8,
        encryption_algorithm=pkcs12.serialization.NoEncryption()).decode('utf-8')
    
    certificate_pem = certificate.public_bytes(
        encoding=pkcs12.serialization.Encoding.PEM).decode('utf-8')

    # Informações adicionais do certificado
    subject = certificate.subject
    issuer = certificate.issuer
    
    # Calcular localKeyID usando a chave privada
    local_key_id = private_key.private_bytes(
        encoding=pkcs12.serialization.Encoding.DER,
        format=pkcs12.serialization.PrivateFormat.PKCS8,
        encryption_algorithm=pkcs12.serialization.NoEncryption())
    
    local_key_id_hex = hashes.Hash(hashes.SHA1(), backend=default_backend())
    local_key_id_hex.update(local_key_id)
    local_key_id_hex = local_key_id_hex.finalize().hex().upper()
    
    # Corrigir obtenção dos valores do sujeito
    subject_values = [f"{attribute.oid._name}={attribute.value}" for attribute in subject]
    
    result = f"""
{certificate_pem}

Bag Attributes
    localKeyID: {local_key_id_hex}
    friendlyName: {subject_values}
subject={subject}
issuer={issuer}
{private_key_pem}
"""
    return result

result = load_private_key_and_certificate(pfx_path, pfx_password)
print(result)

it gives me the result I want, so I try to rewrite it in plpython3u like this:

CREATE OR REPLACE FUNCTION load_private_key_and_certificate(pfx_data bytea, pfx_password text)
RETURNS text AS $$
from cryptography.hazmat.primitives.serialization import pkcs12
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes

def load_private_key_and_certificate(pfx_data, pfx_password):
    '''Lê a chave privada e o certificado e retorna como codificados em PEM'''
    pfx_password = pfx_password.encode('utf-8')
    
    private_key, certificate, additional_certificates = pkcs12.load_key_and_certificates(
        pfx_data, pfx_password)
    
    private_key_pem = private_key.private_bytes(
        encoding=pkcs12.serialization.Encoding.PEM,
        format=pkcs12.serialization.PrivateFormat.PKCS8,
        encryption_algorithm=pkcs12.serialization.NoEncryption()).decode('utf-8')
    
    certificate_pem = certificate.public_bytes(
        encoding=pkcs12.serialization.Encoding.PEM).decode('utf-8')

    # Informações adicionais do certificado
    subject = certificate.subject
    issuer = certificate.issuer
    
    # Calcular localKeyID usando a chave privada
    local_key_id = private_key.private_bytes(
        encoding=pkcs12.serialization.Encoding.DER,
        format=pkcs12.serialization.PrivateFormat.PKCS8,
        encryption_algorithm=pkcs12.serialization.NoEncryption())
    
    local_key_id_hex = hashes.Hash(hashes.SHA1(), backend=default_backend())
    local_key_id_hex.update(local_key_id)
    local_key_id_hex = local_key_id_hex.finalize().hex().upper()
    
    # Corrigir obtenção dos valores do sujeito
    subject_values = [f"{attribute.oid._name}={attribute.value}" for attribute in subject]
    
    result = f"""
{certificate_pem}

Bag Attributes
    localKeyID: {local_key_id_hex}
    friendlyName: {subject_values}
subject={subject}
issuer={issuer}
{private_key_pem}
"""
    return result
$$ LANGUAGE plpython3u;

These functions have one objective, to extract private_key and public_key from a .pfx file, and they actually do that, they are both printing the .pfx file but the difference is in how they read this .pfx file, in my pure python function, it reads the file from a directory, and in my plpython3u function it reads the file in bytes and returns the keys..

The problem is when I use the keys from the second function, I try to pass the keys obtained in this function here:

CREATE OR REPLACE FUNCTION public.fpy_sicoob_auth(
    chave_privada text 
)
RETURNS TEXT
LANGUAGE plpython3u
AS $function$
import requests
import json 
import tempfile 
import os

url = 'my url'
payload = 'my payload'
header = {
    'Content-Type': 'application/x-www-form-urlencoded'
}
plpy.notice('%', chave_privada);
with tempfile.NamedTemporaryFile(delete=False) as temp_key_file:
    temp_key_file.write(chave_privada.encode('utf-8'))
    temp_key_path = temp_key_file.name

response = requests.post(url, data=payload, headers=header, cert=temp_key_path, verify=False)

temp_key_file.close()
# Remova o arquivo temporário após o uso
try:
    os.remove(temp_key_path)
except Exception as e:
    return(f"Erro ao excluir o arquivo temporário: {e}")

response_json = json.loads(response.text)
access_token = response_json["access_token"]

return access_token
$function$
;

using the keys that I get in pure python, I can make use of the function, but using the keys that I get in the plpython3u function I get the error:

   Erro SQL [38000]: ERRO: requests.exceptions.SSLError: HTTPSConnectionPool(host='auth.sicoob.com.br', port=443): Max retries exceeded with url: /auth/realms/cooperado/protocol/openid-connect/token (Caused by SSLError(SSLError(524297, '[SSL] PEM lib (_ssl.c:3926)')))
  Onde: Traceback (most recent call last):
  PL/Python function "fpy_sicoob_auth", line 17, in <module>
    response = requests.post(url, data=payload, headers=header, cert=temp_key_path, verify=False)
  PL/Python function "fpy_sicoob_auth", line 114, in post
  PL/Python function "fpy_sicoob_auth", line 58, in request
  PL/Python function "fpy_sicoob_auth", line 588, in request
  PL/Python function "fpy_sicoob_auth", line 702, in send
  PL/Python function "fpy_sicoob_auth", line 516, in send
função PL/Python "fpy_sicoob_auth"

Does this happen because in the plpython function I obtain the keys from a certificate that is in bytea format? Can anyone help me with any information?

0

There are 0 best solutions below