Skip to content

Add support for mariadb's ed25519 authentication #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: stein-rdo
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions auth_ed25519.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# taken from https://github.com/PyMySQL/PyMySQL/pull/791/commits
# stripped the patches for tests and development files

From: Damien Ciabrini <damien.ciabrini@gmail.com>
Date: Tue, 4 Jun 2019 09:28:29 +0200
Subject: [PATCH] Support for MariaDB's auth_ed25519 authentication plugin
(#786)

diff --git a/pymysql/_auth.py b/pymysql/_auth.py
index aa082dfe..0a09de4e 100644
--- a/pymysql/_auth.py
+++ b/pymysql/_auth.py
@@ -114,6 +114,66 @@ def _hash_password_323(password):
return struct.pack(">LL", r1, r2)


+# MariaDB's client_ed25519-plugin
+# https://mariadb.com/kb/en/library/connection/#client_ed25519-plugin
+
+_nacl_bindings = False
+
+
+def _init_nacl():
+ global _nacl_bindings
+ try:
+ from nacl import bindings
+ _nacl_bindings = bindings
+ except ImportError:
+ raise RuntimeError("'pynacl' package is required for ed25519_password auth method")
+
+
+def _scalar_clamp(s32):
+ ba = bytearray(s32)
+ ba0 = bytes(bytearray([ba[0] & 248]))
+ ba31 = bytes(bytearray([(ba[31] & 127) | 64]))
+ return ba0 + bytes(s32[1:31]) + ba31
+
+
+def ed25519_password(password, scramble):
+ """Sign a random scramble with elliptic curve Ed25519.
+
+ Secret and public key are derived from password.
+ """
+ # variable names based on rfc8032 section-5.1.6
+ #
+ if not _nacl_bindings:
+ _init_nacl()
+
+ # h = SHA512(password)
+ h = hashlib.sha512(password).digest()
+
+ # s = prune(first_half(h))
+ s = _scalar_clamp(h[:32])
+
+ # r = SHA512(second_half(h) || M)
+ r = hashlib.sha512(h[32:] + scramble).digest()
+
+ # R = encoded point [r]B
+ r = _nacl_bindings.crypto_core_ed25519_scalar_reduce(r)
+ R = _nacl_bindings.crypto_scalarmult_ed25519_base_noclamp(r)
+
+ # A = encoded point [s]B
+ A = _nacl_bindings.crypto_scalarmult_ed25519_base_noclamp(s)
+
+ # k = SHA512(R || A || M)
+ k = hashlib.sha512(R + A + scramble).digest()
+
+ # S = (k * s + r) mod L
+ k = _nacl_bindings.crypto_core_ed25519_scalar_reduce(k)
+ ks = _nacl_bindings.crypto_core_ed25519_scalar_mul(k, s)
+ S = _nacl_bindings.crypto_core_ed25519_scalar_add(ks, r)
+
+ # signature = R || S
+ return R + S
+
+
# sha256_password


diff --git a/pymysql/connections.py b/pymysql/connections.py
index d9ade9a2..df092929 100644
--- a/pymysql/connections.py
+++ b/pymysql/connections.py
@@ -889,6 +889,8 @@ def _process_auth(self, plugin_name, auth_packet):
return _auth.sha256_password_auth(self, auth_packet)
elif plugin_name == b"mysql_native_password":
data = _auth.scramble_native_password(self.password, auth_packet.read_all())
+ elif plugin_name == b'client_ed25519':
+ data = _auth.ed25519_password(self.password, auth_packet.read_all())
elif plugin_name == b"mysql_old_password":
data = _auth.scramble_old_password(self.password, auth_packet.read_all()) + b'\0'
elif plugin_name == b"mysql_clear_password":
23 changes: 21 additions & 2 deletions python-PyMySQL.spec
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,29 @@

%if 0%{?fedora} || 0%{?rhel} > 7
%global with_python3 1
%else
%global with_python2 1
%endif

Name: python-%{pypi_name}
Version: 0.9.2
Release: 2%{?dist}
Version: 0.9.3
Release: 2%{?dist}.rdo.1
Summary: Pure-Python MySQL client library

License: MIT
URL: https://pypi.python.org/pypi/%{pypi_name}/
Source0: https://files.pythonhosted.org/packages/source/P/PyMySQL/PyMySQL-%{version}.tar.gz

Patch1: auth_ed25519.patch

BuildArch: noarch

%if 0%{?with_python2}
# for python2
BuildRequires: python2-devel
BuildRequires: python2-setuptools
BuildRequires: python2-cryptography
%endif

%if 0%{?with_python3}
# for python3
Expand All @@ -33,6 +39,7 @@ to be a drop-in replacement for MySQLdb and work on CPython, PyPy, IronPython
and Jython.


%if 0%{?with_python2}
%package -n python2-%{pypi_name}
Summary: Pure-Python MySQL client library
Requires: python2-cryptography
Expand All @@ -42,6 +49,7 @@ Requires: python2-cryptography
This package contains a pure-Python MySQL client library. The goal of PyMySQL is
to be a drop-in replacement for MySQLdb and work on CPython, PyPy, IronPython
and Jython.
%endif

%if 0%{?with_python3}
%package -n python%{python3_pkgversion}-%{pypi_name}
Expand All @@ -58,24 +66,29 @@ and Jython.

%prep
%setup -qn %{pypi_name}-%{version}
%patch1 -p1
rm -rf %{pypi_name}.egg-info
# Remove tests files so they are not installed globally.
rm -rf tests


%build
%if 0%{?with_python2}
%py2_build
%endif
%if 0%{?with_python3}
%py3_build
%endif


%install
%if 0%{?with_python2}
%py2_install
# Remove shebang
#for lib in %{buildroot}%{python2_sitelib}/pymysql/tests/thirdparty/test_MySQLdb/*.py; do
# sed -i '1{\@^#!/usr/bin/env python@d}' $lib
#done
%endif

%if 0%{?with_python3}
%py3_install
Expand All @@ -90,11 +103,13 @@ rm -rf tests
# Tests cannot be launch on koji, they require a mysqldb running.


%if 0%{?with_python2}
%files -n python2-%{pypi_name}
%license LICENSE
%doc README.rst
%{python2_sitelib}/%{pypi_name}-%{version}-py%{python2_version}.egg-info/
%{python2_sitelib}/pymysql/
%endif

%if 0%{?with_python3}
%files -n python%{python3_pkgversion}-%{pypi_name}
Expand All @@ -105,6 +120,10 @@ rm -rf tests
%endif

%changelog
* Fri Mar 27 2020 Damien Ciabrini <dciabrin@redhat.com> - 0.9.3-2.rdo.1
- Aligned to Fedora 32 version
- Added support for mariadb auth_ed25519 (#791)

* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.2-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild

Expand Down
2 changes: 1 addition & 1 deletion sources
Original file line number Diff line number Diff line change
@@ -1 +1 @@
SHA512 (PyMySQL-0.9.2.tar.gz) = 4918802808fb12417db682831290adfa5a785ca34da5674b7a8ccc7c942a1de424c3085282912df326131e978daf771d71c6b33aeb3cb2590c70b5ff6e557b07
SHA512 (PyMySQL-0.9.3.tar.gz) = 2056bc4aca7a600ca50214b399edc6f3068b288c426aecb115db148f645b0ec7e9a1a7134cf67f39d4820ea59a925dc1ce3ed0e383fb5e16e0651e87449824f9