Вопрос или проблема
У меня есть следующий код на Python:
import base64
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import serialization
private_key_pem = """
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDCpA0jK8IgLtV+
b/X3t+cmt9r3owRyD
Ywbm6Kbsvj/pXNYaI47toIk=
-----END PRIVATE KEY-----
"""
data = b"""GET
/v1/contas/aa/aa
agencia=3995&conta=75557
eyJhbGciOiJSUzUxMiJ9.ew0KIsDQoiYXVkIjogImh0dHBzOi8vb3BlbmFwaS1heHdheS5hcGkuc
1728392567000
2024-10-08T10:02:00-00:00
SHA256"""
private_key = serialization.load_pem_private_key(
private_key_pem.encode('utf-8'),
password=None,
backend=default_backend()
)
signature = private_key.sign(
data,
padding.PKCS1v15(),
hashes.SHA256()
)
signature_b64 = base64.b64encode(signature).decode('utf-8')
signature_b64 = signature_b64.rstrip('=\n').replace('+', '-').replace("https://stackoverflow.com/", '_')
print(signature_b64)
Эта функция выше создает подпись с использованием закрытого ключа и работает без проблем на Python. Но мне нужно передать эту функцию в базу данных PostgreSQL, используя plpython3u, поэтому я replicated это следующим образом:
DROP FUNCTION IF EXISTS public.teste;
CREATE OR REPLACE FUNCTION public.teste()
RETURNS TEXT AS $$
import base64
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import serialization
private_key_pem = '''-----BEGIN PRIVATE KEY-----
mt9r3owRyDOej0p9qDP0kO0v3eQsKSKmMnV1/WDo0r6Wo/cjsMs4mFC9O
nqvy26/1xE1+mHBoC/+rvhoEn59kzL
Ywbm6Kbsvj/pXNYaI47toIk=
-----END PRIVATE KEY-----'''
data = """GET
/v1/contas/aa/aa
agencia=aa&conta=aa
eyJhbGciOiJSUzUxMiJ9.ew0KInZlciI6ICIxLjAiLA0KImlzcyI6Ih5LmFwaS5wcmViYW5jby5jb20uYnIvYXV0aC9zZXJ2ZXIvdjEuMS90b2tlbiIsDQKGn2JWQ
1728392567000
2024-10-08T10:02:00-00:00
SHA256"""
private_key = serialization.load_pem_private_key(
private_key_pem.encode('utf-8'),
password=None,
backend=default_backend()
)
signature = private_key.sign(
data,
padding.PKCS1v15(),
hashes.SHA256()
)
signature_b64 = base64.b64encode(signature).decode('utf-8')
signature_b64 = signature_b64.rstrip('=\n').replace('+', '-').replace("https://stackoverflow.com/", '_')
plpy.notice(signature_b64)
$$ LANGUAGE plpython3u;
Функции абсолютно одинаковы, но при выполнении функции в базе данных я получаю ошибку:
Ошибка SQL [38000]: ERROR: ValueError: (‘Не удалось десериализовать данные ключа. Данные могут быть в неправильном формате, предоставленный пароль может быть неверным, он может быть зашифрован с использованием неподдерживаемого алгоритма или может быть неподдерживаемым типом ключа (например, кривые EC с явными параметрами).’, [<OpenSSLError(code=503841036, lib=60, reason=524556, reason_text=unsupported)>])
Где: Traceback (самый последний вызов):
PL/Python функция “teste”, строка 44, в
private_key = serialization.load_pem_private_key(
PL/Python функция “teste”
Я не понимаю, почему возникает ошибка, поскольку данные и функции абсолютно идентичны.
Ответ или решение
Проблема, с которой вы столкнулись, связана с форматом закрытого ключа, который вы используете в вашей функции PL/Python в PostgreSQL. Ошибка, которую вы получили, указывает на то, что библиотека cryptography
не может десериализовать данные ключа, вероятно из-за неверного формата.
Ошибка десериализации ключа
Ваша ошибка может быть вызвана несколькими причинами:
-
Неверный формат ключа: Убедитесь, что закрытый ключ правильно отформатирован и соответствует требуемому стандарту. Например, если вы используете ключ в формате PKCS#8, он должен начинаться с
-----BEGIN PRIVATE KEY-----
, а если в формате PKCS#1 —-----BEGIN RSA PRIVATE KEY-----
. -
Пробелы и переводы строк: Проверьте, нет ли лишних пробелов, символов перевода строки или ошибок при копировании ключа. Даже небольшие изменения могут вызвать проблемы при десериализации.
-
Совместимость с библиотекой: Убедитесь, что версия библиотеки
cryptography
, используемая в среде PostgreSQL, поддерживает формат вашего ключа.
Решение проблемы
Вот что вы можете сделать для решения вашей проблемы:
-
Замените закрытый ключ: Попробуйте использовать другой закрытый ключ. Убедитесь, что он корректен и соответствует формату, который может обрабатывать библиотека
cryptography
. -
Проверьте библиотеку: Убедитесь, что вы используете совместимую версию библиотеки
cryptography
в вашей среде PostgreSQL. Версия библиотеки в PostgreSQL может отличаться от той, что установлена в вашем локальном Python. -
Проверьте код: Убедитесь, что код не имеет лишних символов и корректно отформатирован. Иногда проблемы могут возникнуть из-за ошибок в коде, даже если они неочевидны при первом взгляде.
Вот пример, как можно передавать закрытый ключ и данные в вашем коде:
private_key_pem = """
-----BEGIN PRIVATE KEY-----
...ваш ключ...
-----END PRIVATE KEY-----
"""
data = b"""GET
/v1/contas/aa/aa
agencia=3995&conta=75557
eyJhbGciOiJSUzUxMiJ9....
...
SHA256"""
Обратите внимание на то, что переменная data
должна быть типом bytes
(в вашем случае это строка, которая будет преобразована в байты).
Заключение
Если перечисленные выше шаги не дадут результата, рекомендую попробовать:
- Перегенерировать ваш закрытый ключ.
- Убедиться, что формат ключа и код совместимы с используемыми вами библиотеками.
- Если проблема остается нерешенной, предоставьте дополнительную информацию об ошибке или используемом окружении, чтобы можно было более детально проанализировать проблему.
Используя эти рекомендации, вы сможете устранить проблему с десериализацией ключа.