Skip to content

Commit 7b2d69f

Browse files
committed
Add support for mariadb's auth_ed25519
Include #791 [1] into the current release of PyMySQL to support mariadb's auth_ed25519. This patch can be dropped once the PR have landed upstream (currently depending on a new release of pynacl). [1] PyMySQL/PyMySQL#791 Related-Bug: #1868454
1 parent 8976cf4 commit 7b2d69f

File tree

2 files changed

+100
-1
lines changed

2 files changed

+100
-1
lines changed

auth_ed25519.patch

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# taken from https://github.com/PyMySQL/PyMySQL/pull/791/commits
2+
# stripped the patches for tests and development files
3+
4+
From: Damien Ciabrini <damien.ciabrini@gmail.com>
5+
Date: Tue, 4 Jun 2019 09:28:29 +0200
6+
Subject: [PATCH] Support for MariaDB's auth_ed25519 authentication plugin
7+
(#786)
8+
9+
diff --git a/pymysql/_auth.py b/pymysql/_auth.py
10+
index aa082dfe..0a09de4e 100644
11+
--- a/pymysql/_auth.py
12+
+++ b/pymysql/_auth.py
13+
@@ -114,6 +114,66 @@ def _hash_password_323(password):
14+
return struct.pack(">LL", r1, r2)
15+
16+
17+
+# MariaDB's client_ed25519-plugin
18+
+# https://mariadb.com/kb/en/library/connection/#client_ed25519-plugin
19+
+
20+
+_nacl_bindings = False
21+
+
22+
+
23+
+def _init_nacl():
24+
+ global _nacl_bindings
25+
+ try:
26+
+ from nacl import bindings
27+
+ _nacl_bindings = bindings
28+
+ except ImportError:
29+
+ raise RuntimeError("'pynacl' package is required for ed25519_password auth method")
30+
+
31+
+
32+
+def _scalar_clamp(s32):
33+
+ ba = bytearray(s32)
34+
+ ba0 = bytes(bytearray([ba[0] & 248]))
35+
+ ba31 = bytes(bytearray([(ba[31] & 127) | 64]))
36+
+ return ba0 + bytes(s32[1:31]) + ba31
37+
+
38+
+
39+
+def ed25519_password(password, scramble):
40+
+ """Sign a random scramble with elliptic curve Ed25519.
41+
+
42+
+ Secret and public key are derived from password.
43+
+ """
44+
+ # variable names based on rfc8032 section-5.1.6
45+
+ #
46+
+ if not _nacl_bindings:
47+
+ _init_nacl()
48+
+
49+
+ # h = SHA512(password)
50+
+ h = hashlib.sha512(password).digest()
51+
+
52+
+ # s = prune(first_half(h))
53+
+ s = _scalar_clamp(h[:32])
54+
+
55+
+ # r = SHA512(second_half(h) || M)
56+
+ r = hashlib.sha512(h[32:] + scramble).digest()
57+
+
58+
+ # R = encoded point [r]B
59+
+ r = _nacl_bindings.crypto_core_ed25519_scalar_reduce(r)
60+
+ R = _nacl_bindings.crypto_scalarmult_ed25519_base_noclamp(r)
61+
+
62+
+ # A = encoded point [s]B
63+
+ A = _nacl_bindings.crypto_scalarmult_ed25519_base_noclamp(s)
64+
+
65+
+ # k = SHA512(R || A || M)
66+
+ k = hashlib.sha512(R + A + scramble).digest()
67+
+
68+
+ # S = (k * s + r) mod L
69+
+ k = _nacl_bindings.crypto_core_ed25519_scalar_reduce(k)
70+
+ ks = _nacl_bindings.crypto_core_ed25519_scalar_mul(k, s)
71+
+ S = _nacl_bindings.crypto_core_ed25519_scalar_add(ks, r)
72+
+
73+
+ # signature = R || S
74+
+ return R + S
75+
+
76+
+
77+
# sha256_password
78+
79+
80+
diff --git a/pymysql/connections.py b/pymysql/connections.py
81+
index d9ade9a2..df092929 100644
82+
--- a/pymysql/connections.py
83+
+++ b/pymysql/connections.py
84+
@@ -889,6 +889,8 @@ def _process_auth(self, plugin_name, auth_packet):
85+
return _auth.sha256_password_auth(self, auth_packet)
86+
elif plugin_name == b"mysql_native_password":
87+
data = _auth.scramble_native_password(self.password, auth_packet.read_all())
88+
+ elif plugin_name == b'client_ed25519':
89+
+ data = _auth.ed25519_password(self.password, auth_packet.read_all())
90+
elif plugin_name == b"mysql_old_password":
91+
data = _auth.scramble_old_password(self.password, auth_packet.read_all()) + b'\0'
92+
elif plugin_name == b"mysql_clear_password":

python-PyMySQL.spec

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66

77
Name: python-%{pypi_name}
88
Version: 0.9.2
9-
Release: 2%{?dist}
9+
Release: 2%{?dist}.rdo.1
1010
Summary: Pure-Python MySQL client library
1111

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

16+
Patch1: auth_ed25519.patch
17+
1618
BuildArch: noarch
1719

1820
# for python2
@@ -58,6 +60,7 @@ and Jython.
5860

5961
%prep
6062
%setup -qn %{pypi_name}-%{version}
63+
%patch1 -p1
6164
rm -rf %{pypi_name}.egg-info
6265
# Remove tests files so they are not installed globally.
6366
rm -rf tests
@@ -105,6 +108,10 @@ rm -rf tests
105108
%endif
106109

107110
%changelog
111+
* Fri Mar 27 2020 Damien Ciabrini <dciabrin@redhat.com> - 0.9.2-2.rdo.1
112+
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
113+
- Added support for mariadb auth_ed25519 (#791)
114+
108115
* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.2-2
109116
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
110117

0 commit comments

Comments
 (0)