@@ -8,7 +8,7 @@ namespace MySqlConnector.Authentication.Ed25519;
8
8
/// <summary>
9
9
/// Provides an implementation of the Parsec authentication plugin for MariaDB.
10
10
/// </summary>
11
- public sealed class ParsecAuthenticationPlugin : IAuthenticationPlugin
11
+ public sealed class ParsecAuthenticationPlugin : IAuthenticationPlugin3
12
12
{
13
13
/// <summary>
14
14
/// Registers the Parsec authentication plugin with MySqlConnector. You must call this method once before
@@ -29,6 +29,15 @@ public static void Install()
29
29
/// Creates the authentication response.
30
30
/// </summary>
31
31
public byte [ ] CreateResponse ( string password , ReadOnlySpan < byte > authenticationData )
32
+ {
33
+ CreateResponseAndPasswordHash ( password , authenticationData , out var response , out _ ) ;
34
+ return response ;
35
+ }
36
+
37
+ /// <summary>
38
+ /// Creates the authentication response.
39
+ /// </summary>
40
+ public void CreateResponseAndPasswordHash ( string password , ReadOnlySpan < byte > authenticationData , out byte [ ] authenticationResponse , out byte [ ] passwordHash )
32
41
{
33
42
// first 32 bytes are server scramble
34
43
var serverScramble = authenticationData . Slice ( 0 , 32 ) ;
@@ -54,32 +63,37 @@ public byte[] CreateResponse(string password, ReadOnlySpan<byte> authenticationD
54
63
var salt = extendedSalt . Slice ( 2 ) ;
55
64
56
65
// derive private key using PBKDF2-SHA512
57
- byte [ ] privateKey ;
66
+ byte [ ] privateKeySeed ;
58
67
#if NET6_0_OR_GREATER
59
- privateKey = Rfc2898DeriveBytes . Pbkdf2 ( Encoding . UTF8 . GetBytes ( password ) , salt , iterationCount , HashAlgorithmName . SHA512 , 32 ) ;
68
+ privateKeySeed = Rfc2898DeriveBytes . Pbkdf2 ( Encoding . UTF8 . GetBytes ( password ) , salt , iterationCount , HashAlgorithmName . SHA512 , 32 ) ;
60
69
#elif NET472_OR_GREATER || NETSTANDARD2_1_OR_GREATER
61
70
using ( var pbkdf2 = new Rfc2898DeriveBytes ( Encoding . UTF8 . GetBytes ( password ) , salt . ToArray ( ) , iterationCount , HashAlgorithmName . SHA512 ) )
62
- privateKey = pbkdf2 . GetBytes ( 32 ) ;
71
+ privateKeySeed = pbkdf2 . GetBytes ( 32 ) ;
63
72
#else
64
- privateKey = Microsoft . AspNetCore . Cryptography . KeyDerivation . KeyDerivation . Pbkdf2 (
73
+ privateKeySeed = Microsoft . AspNetCore . Cryptography . KeyDerivation . KeyDerivation . Pbkdf2 (
65
74
password , salt . ToArray ( ) , Microsoft . AspNetCore . Cryptography . KeyDerivation . KeyDerivationPrf . HMACSHA512 ,
66
75
iterationCount , numBytesRequested : 32 ) ;
67
76
#endif
68
- var expandedPrivateKey = Chaos . NaCl . Ed25519 . ExpandedPrivateKeyFromSeed ( privateKey ) ;
77
+ Chaos . NaCl . Ed25519 . KeyPairFromSeed ( out var publicKey , out var privateKey , privateKeySeed ) ;
69
78
70
79
// generate Ed25519 keypair and sign concatenated scrambles
71
80
var message = new byte [ serverScramble . Length + clientScramble . Length ] ;
72
81
serverScramble . CopyTo ( message ) ;
73
82
clientScramble . CopyTo ( message . AsSpan ( serverScramble . Length ) ) ;
74
83
75
- var signature = Chaos . NaCl . Ed25519 . Sign ( message , expandedPrivateKey ) ;
84
+ var signature = Chaos . NaCl . Ed25519 . Sign ( message , privateKey ) ;
85
+
86
+ #if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER
87
+ CryptographicOperations . ZeroMemory ( privateKey ) ;
88
+ #endif
76
89
77
90
// return client scramble followed by signature
78
- var response = new byte [ clientScramble . Length + signature . Length ] ;
79
- clientScramble . CopyTo ( response . AsSpan ( ) ) ;
80
- signature . CopyTo ( response . AsSpan ( clientScramble . Length ) ) ;
81
-
82
- return response ;
91
+ authenticationResponse = new byte [ clientScramble . Length + signature . Length ] ;
92
+ clientScramble . CopyTo ( authenticationResponse . AsSpan ( ) ) ;
93
+ signature . CopyTo ( authenticationResponse . AsSpan ( clientScramble . Length ) ) ;
94
+
95
+ // "password hash" for parsec is the extended salt followed by the public key
96
+ passwordHash = [ ( byte ) 'P' , ( byte ) iterationCount , .. salt , .. publicKey ] ;
83
97
}
84
98
85
99
private ParsecAuthenticationPlugin ( )
0 commit comments