Skip to content

Commit 208f2ec

Browse files
committed
Add Parsec authentication plugin implementation.
Create a new ServerFeature for parsec. Drop netstandard2.0 support. PBKDF2-SHA512 support was only added in .NET Framework 4.7.2 and .NET Standard 2.1. Signed-off-by: Bradley Grainger <[email protected]>
1 parent 11937af commit 208f2ec

23 files changed

+547
-109
lines changed

Diff for: .ci/config/config.compression.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"SocketPath": "./../../../../.ci/run/mysql/mysqld.sock",
55
"PasswordlessUser": "no_password",
66
"SecondaryDatabase": "testdb2",
7-
"UnsupportedFeatures": "Ed25519,QueryAttributes,Redirection,StreamingResults,Tls11,TlsFingerprintValidation,UnixDomainSocket,ZeroDateTime",
7+
"UnsupportedFeatures": "Ed25519,QueryAttributes,ParsecAuthentication,Redirection,StreamingResults,Tls11,TlsFingerprintValidation,UnixDomainSocket,ZeroDateTime",
88
"MySqlBulkLoaderLocalCsvFile": "../../../../tests/TestData/LoadData_UTF8_BOM_Unix.CSV",
99
"MySqlBulkLoaderLocalTsvFile": "../../../../tests/TestData/LoadData_UTF8_BOM_Unix.TSV"
1010
}

Diff for: .ci/config/config.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"SocketPath": "./../../../../.ci/run/mysql/mysqld.sock",
55
"PasswordlessUser": "no_password",
66
"SecondaryDatabase": "testdb2",
7-
"UnsupportedFeatures": "Ed25519,QueryAttributes,Redirection,StreamingResults,Tls11,TlsFingerprintValidation,UnixDomainSocket,ZeroDateTime",
7+
"UnsupportedFeatures": "Ed25519,QueryAttributes,ParsecAuthentication,Redirection,StreamingResults,Tls11,TlsFingerprintValidation,UnixDomainSocket,ZeroDateTime",
88
"MySqlBulkLoaderLocalCsvFile": "../../../../tests/TestData/LoadData_UTF8_BOM_Unix.CSV",
99
"MySqlBulkLoaderLocalTsvFile": "../../../../tests/TestData/LoadData_UTF8_BOM_Unix.TSV"
1010
}

Diff for: .ci/docker-run.sh

+6
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ for i in `seq 1 120`; do
7979
if [ $? -ne 0 ]; then exit $?; fi
8080
fi
8181

82+
if [[ $OMIT_FEATURES != *"ParsecAuthentication"* ]]; then
83+
echo "Installing auth_parsec component"
84+
docker exec mysql bash -c "$MYSQL -uroot -ptest < /etc/mysql/conf.d/init_parsec.sql"
85+
if [ $? -ne 0 ]; then exit $?; fi
86+
fi
87+
8288
if [[ $OMIT_FEATURES != *"QueryAttributes"* ]]; then
8389
echo "Installing query_attributes component"
8490
docker exec mysql $MYSQL -uroot -ptest -e "INSTALL COMPONENT 'file://component_query_attributes';"

Diff for: .ci/server/init_parsec.sql

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
INSTALL SONAME 'auth_parsec';
2+
CREATE USER 'parsec-user'@'%' IDENTIFIED via parsec using PASSWORD('P@rs3c-Pa55');
3+
GRANT ALL PRIVILEGES ON *.* TO 'parsec-user'@'%';

Diff for: azure-pipelines.yml

+9-9
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
arguments: 'tests\IntegrationTests\IntegrationTests.csproj -c MySqlData'
5252
testRunTitle: 'MySql.Data integration tests'
5353
env:
54-
DATA__UNSUPPORTEDFEATURES: 'Ed25519,QueryAttributes,StreamingResults,TlsFingerprintValidation,UnixDomainSocket'
54+
DATA__UNSUPPORTEDFEATURES: 'Ed25519,QueryAttributes,ParsecAuthentication,StreamingResults,TlsFingerprintValidation,UnixDomainSocket'
5555
DATA__CONNECTIONSTRING: 'server=localhost;port=3306;user id=root;password=test;database=mysqltest;ssl mode=none;DefaultCommandTimeout=3600'
5656
DATA__CERTIFICATESPATH: '$(Build.Repository.LocalPath)\.ci\server\certs\'
5757
DATA__MYSQLBULKLOADERLOCALCSVFILE: '$(Build.Repository.LocalPath)\tests\TestData\LoadData_UTF8_BOM_Unix.CSV'
@@ -120,7 +120,7 @@ jobs:
120120
arguments: '-c Release --no-restore -p:TestTfmsInParallel=false'
121121
testRunTitle: ${{ format('{0}, $(Agent.OS), {1}, {2}', 'mysql:8.0', 'net481/net9.0', 'No SSL') }}
122122
env:
123-
DATA__UNSUPPORTEDFEATURES: 'Ed25519,QueryAttributes,Redirection,StreamingResults,Tls11,TlsFingerprintValidation,UnixDomainSocket'
123+
DATA__UNSUPPORTEDFEATURES: 'Ed25519,QueryAttributes,ParsecAuthentication,Redirection,StreamingResults,Tls11,TlsFingerprintValidation,UnixDomainSocket'
124124
DATA__CONNECTIONSTRING: 'server=localhost;port=3306;user id=mysqltest;password=test;database=mysqltest;ssl mode=none;DefaultCommandTimeout=3600;AllowPublicKeyRetrieval=True;UseCompression=True'
125125

126126
- job: windows_integration_tests_2
@@ -158,7 +158,7 @@ jobs:
158158
arguments: '-c Release --no-restore -p:TestTfmsInParallel=false'
159159
testRunTitle: ${{ format('{0}, $(Agent.OS), {1}, {2}', 'mysql:8.0', 'net8.0', 'No SSL') }}
160160
env:
161-
DATA__UNSUPPORTEDFEATURES: 'Ed25519,QueryAttributes,Redirection,StreamingResults,Tls11,TlsFingerprintValidation,UnixDomainSocket'
161+
DATA__UNSUPPORTEDFEATURES: 'Ed25519,QueryAttributes,ParsecAuthentication,Redirection,StreamingResults,Tls11,TlsFingerprintValidation,UnixDomainSocket'
162162
DATA__CONNECTIONSTRING: 'server=localhost;port=3306;user id=mysqltest;password=test;database=mysqltest;ssl mode=none;DefaultCommandTimeout=3600;AllowPublicKeyRetrieval=True'
163163

164164
- job: linux_integration_tests
@@ -171,27 +171,27 @@ jobs:
171171
'MySQL 8.0':
172172
image: 'mysql:8.0'
173173
connectionStringExtra: 'AllowPublicKeyRetrieval=True'
174-
unsupportedFeatures: 'Ed25519,Redirection,StreamingResults,Tls11,TlsFingerprintValidation,ZeroDateTime'
174+
unsupportedFeatures: 'Ed25519,ParsecAuthentication,Redirection,StreamingResults,Tls11,TlsFingerprintValidation,ZeroDateTime'
175175
'MySQL 8.4':
176176
image: 'mysql:8.4'
177177
connectionStringExtra: 'AllowPublicKeyRetrieval=True'
178-
unsupportedFeatures: 'Ed25519,Redirection,StreamingResults,Tls11,TlsFingerprintValidation,ZeroDateTime'
178+
unsupportedFeatures: 'Ed25519,ParsecAuthentication,Redirection,StreamingResults,Tls11,TlsFingerprintValidation,ZeroDateTime'
179179
'MySQL 9.2':
180180
image: 'mysql:9.2'
181181
connectionStringExtra: 'AllowPublicKeyRetrieval=True'
182-
unsupportedFeatures: 'Ed25519,Redirection,StreamingResults,Tls11,TlsFingerprintValidation,ZeroDateTime'
182+
unsupportedFeatures: 'Ed25519,ParsecAuthentication,Redirection,StreamingResults,Tls11,TlsFingerprintValidation,ZeroDateTime'
183183
'MariaDB 10.6':
184184
image: 'mariadb:10.6'
185185
connectionStringExtra: ''
186-
unsupportedFeatures: 'CachingSha2Password,CancelSleepSuccessfully,Json,RoundDateTime,QueryAttributes,Redirection,Sha256Password,Tls11,TlsFingerprintValidation,UuidToBin'
186+
unsupportedFeatures: 'CachingSha2Password,CancelSleepSuccessfully,Json,RoundDateTime,QueryAttributes,ParsecAuthentication,Redirection,Sha256Password,Tls11,TlsFingerprintValidation,UuidToBin'
187187
'MariaDB 10.11':
188188
image: 'mariadb:10.11'
189189
connectionStringExtra: ''
190-
unsupportedFeatures: 'CachingSha2Password,CancelSleepSuccessfully,Json,RoundDateTime,QueryAttributes,Redirection,Sha256Password,Tls11,TlsFingerprintValidation,UuidToBin'
190+
unsupportedFeatures: 'CachingSha2Password,CancelSleepSuccessfully,Json,RoundDateTime,QueryAttributes,ParsecAuthentication,Redirection,Sha256Password,Tls11,TlsFingerprintValidation,UuidToBin'
191191
'MariaDB 11.4':
192192
image: 'mariadb:11.4'
193193
connectionStringExtra: ''
194-
unsupportedFeatures: 'CachingSha2Password,CancelSleepSuccessfully,Json,RoundDateTime,QueryAttributes,Sha256Password,Tls11,UuidToBin,Redirection'
194+
unsupportedFeatures: 'CachingSha2Password,CancelSleepSuccessfully,Json,RoundDateTime,QueryAttributes,ParsecAuthentication,Sha256Password,Tls11,UuidToBin,Redirection'
195195
'MariaDB 11.6':
196196
image: 'mariadb:11.6'
197197
connectionStringExtra: ''
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System;
2+
using System.Runtime.CompilerServices;
3+
4+
namespace Chaos.NaCl
5+
{
6+
internal static class CryptoBytes
7+
{
8+
public static void Wipe(byte[] data)
9+
{
10+
if (data == null)
11+
throw new ArgumentNullException("data");
12+
InternalWipe(data, 0, data.Length);
13+
}
14+
15+
// Secure wiping is hard
16+
// * the GC can move around and copy memory
17+
// Perhaps this can be avoided by using unmanaged memory or by fixing the position of the array in memory
18+
// * Swap files and error dumps can contain secret information
19+
// It seems possible to lock memory in RAM, no idea about error dumps
20+
// * Compiler could optimize out the wiping if it knows that data won't be read back
21+
// I hope this is enough, suppressing inlining
22+
// but perhaps `RtlSecureZeroMemory` is needed
23+
[MethodImpl(MethodImplOptions.NoInlining)]
24+
internal static void InternalWipe(byte[] data, int offset, int count)
25+
{
26+
Array.Clear(data, offset, count);
27+
}
28+
29+
// shallow wipe of structs
30+
[MethodImpl(MethodImplOptions.NoInlining)]
31+
internal static void InternalWipe<T>(ref T data)
32+
where T : struct
33+
{
34+
data = default(T);
35+
}
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using System;
2+
using System.Security.Cryptography;
3+
using Chaos.NaCl.Internal.Ed25519Ref10;
4+
5+
namespace Chaos.NaCl
6+
{
7+
internal static class Ed25519
8+
{
9+
public static readonly int PublicKeySizeInBytes = 32;
10+
public static readonly int SignatureSizeInBytes = 64;
11+
public static readonly int ExpandedPrivateKeySizeInBytes = 32 * 2;
12+
public static readonly int PrivateKeySeedSizeInBytes = 32;
13+
public static readonly int SharedKeySizeInBytes = 32;
14+
15+
public static void Sign(ArraySegment<byte> signature, ArraySegment<byte> message, ArraySegment<byte> expandedPrivateKey)
16+
{
17+
if (signature.Array == null)
18+
throw new ArgumentNullException("signature.Array");
19+
if (signature.Count != SignatureSizeInBytes)
20+
throw new ArgumentException("signature.Count");
21+
if (expandedPrivateKey.Array == null)
22+
throw new ArgumentNullException("expandedPrivateKey.Array");
23+
if (expandedPrivateKey.Count != ExpandedPrivateKeySizeInBytes)
24+
throw new ArgumentException("expandedPrivateKey.Count");
25+
if (message.Array == null)
26+
throw new ArgumentNullException("message.Array");
27+
Ed25519Operations.crypto_sign2(signature.Array, signature.Offset, message.Array, message.Offset, message.Count, expandedPrivateKey.Array, expandedPrivateKey.Offset);
28+
}
29+
30+
public static byte[] Sign(byte[] message, byte[] expandedPrivateKey)
31+
{
32+
var signature = new byte[SignatureSizeInBytes];
33+
Sign(new ArraySegment<byte>(signature), new ArraySegment<byte>(message), new ArraySegment<byte>(expandedPrivateKey));
34+
return signature;
35+
}
36+
37+
public static byte[] ExpandedPrivateKeyFromSeed(byte[] privateKeySeed)
38+
{
39+
byte[] privateKey;
40+
byte[] publicKey;
41+
KeyPairFromSeed(out publicKey, out privateKey, privateKeySeed);
42+
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER
43+
CryptographicOperations.ZeroMemory(publicKey);
44+
#else
45+
CryptoBytes.Wipe(publicKey);
46+
#endif
47+
return privateKey;
48+
}
49+
50+
public static void KeyPairFromSeed(out byte[] publicKey, out byte[] expandedPrivateKey, byte[] privateKeySeed)
51+
{
52+
if (privateKeySeed == null)
53+
throw new ArgumentNullException("privateKeySeed");
54+
if (privateKeySeed.Length != PrivateKeySeedSizeInBytes)
55+
throw new ArgumentException("privateKeySeed");
56+
var pk = new byte[PublicKeySizeInBytes];
57+
var sk = new byte[ExpandedPrivateKeySizeInBytes];
58+
Ed25519Operations.crypto_sign_keypair(pk, 0, sk, 0, privateKeySeed, 0);
59+
publicKey = pk;
60+
expandedPrivateKey = sk;
61+
}
62+
}
63+
}
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,63 @@
1-
namespace Chaos.NaCl.Internal.Ed25519Ref10;
1+
using System;
22

3-
/*
4-
ge means group element.
5-
6-
Here the group is the set of pairs (x,y) of field elements (see fe.h)
7-
satisfying -x^2 + y^2 = 1 + d x^2y^2
8-
where d = -121665/121666.
3+
namespace Chaos.NaCl.Internal.Ed25519Ref10
4+
{
5+
/*
6+
ge means group element.
97
10-
Representations:
11-
ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
12-
ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
13-
ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
14-
ge_precomp (Duif): (y+x,y-x,2dxy)
15-
*/
8+
Here the group is the set of pairs (x,y) of field elements (see fe.h)
9+
satisfying -x^2 + y^2 = 1 + d x^2y^2
10+
where d = -121665/121666.
1611
17-
internal struct GroupElementP2
18-
{
19-
public FieldElement X;
20-
public FieldElement Y;
21-
public FieldElement Z;
22-
} ;
12+
Representations:
13+
ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
14+
ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
15+
ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
16+
ge_precomp (Duif): (y+x,y-x,2dxy)
17+
*/
2318

24-
internal struct GroupElementP3
25-
{
26-
public FieldElement X;
27-
public FieldElement Y;
28-
public FieldElement Z;
29-
public FieldElement T;
30-
} ;
19+
internal struct GroupElementP2
20+
{
21+
public FieldElement X;
22+
public FieldElement Y;
23+
public FieldElement Z;
24+
} ;
3125

32-
internal struct GroupElementP1P1
33-
{
34-
public FieldElement X;
35-
public FieldElement Y;
36-
public FieldElement Z;
37-
public FieldElement T;
38-
} ;
26+
internal struct GroupElementP3
27+
{
28+
public FieldElement X;
29+
public FieldElement Y;
30+
public FieldElement Z;
31+
public FieldElement T;
32+
} ;
3933

40-
internal struct GroupElementPreComp
41-
{
42-
public FieldElement yplusx;
43-
public FieldElement yminusx;
44-
public FieldElement xy2d;
34+
internal struct GroupElementP1P1
35+
{
36+
public FieldElement X;
37+
public FieldElement Y;
38+
public FieldElement Z;
39+
public FieldElement T;
40+
} ;
4541

46-
public GroupElementPreComp(FieldElement yplusx, FieldElement yminusx, FieldElement xy2d)
42+
internal struct GroupElementPreComp
43+
{
44+
public FieldElement yplusx;
45+
public FieldElement yminusx;
46+
public FieldElement xy2d;
47+
48+
public GroupElementPreComp(FieldElement yplusx, FieldElement yminusx, FieldElement xy2d)
49+
{
50+
this.yplusx = yplusx;
51+
this.yminusx = yminusx;
52+
this.xy2d = xy2d;
53+
}
54+
} ;
55+
56+
internal struct GroupElementCached
4757
{
48-
this.yplusx = yplusx;
49-
this.yminusx = yminusx;
50-
this.xy2d = xy2d;
51-
}
52-
} ;
58+
public FieldElement YplusX;
59+
public FieldElement YminusX;
60+
public FieldElement Z;
61+
public FieldElement T2d;
62+
} ;
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System;
2+
3+
namespace Chaos.NaCl.Internal.Ed25519Ref10
4+
{
5+
internal static partial class LookupTables
6+
{
7+
internal static readonly GroupElementPreComp[] Base2 = new GroupElementPreComp[]{
8+
new GroupElementPreComp(
9+
new FieldElement( 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 ),
10+
new FieldElement( -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378 ),
11+
new FieldElement( -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546 )
12+
),
13+
new GroupElementPreComp(
14+
new FieldElement( 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024 ),
15+
new FieldElement( 16568933,4717097,-11556148,-1102322,15682896,-11807043,16354577,-11775962,7689662,11199574 ),
16+
new FieldElement( 30464156,-5976125,-11779434,-15670865,23220365,15915852,7512774,10017326,-17749093,-9920357 )
17+
),
18+
new GroupElementPreComp(
19+
new FieldElement( 10861363,11473154,27284546,1981175,-30064349,12577861,32867885,14515107,-15438304,10819380 ),
20+
new FieldElement( 4708026,6336745,20377586,9066809,-11272109,6594696,-25653668,12483688,-12668491,5581306 ),
21+
new FieldElement( 19563160,16186464,-29386857,4097519,10237984,-4348115,28542350,13850243,-23678021,-15815942 )
22+
),
23+
new GroupElementPreComp(
24+
new FieldElement( 5153746,9909285,1723747,-2777874,30523605,5516873,19480852,5230134,-23952439,-15175766 ),
25+
new FieldElement( -30269007,-3463509,7665486,10083793,28475525,1649722,20654025,16520125,30598449,7715701 ),
26+
new FieldElement( 28881845,14381568,9657904,3680757,-20181635,7843316,-31400660,1370708,29794553,-1409300 )
27+
),
28+
new GroupElementPreComp(
29+
new FieldElement( -22518993,-6692182,14201702,-8745502,-23510406,8844726,18474211,-1361450,-13062696,13821877 ),
30+
new FieldElement( -6455177,-7839871,3374702,-4740862,-27098617,-10571707,31655028,-7212327,18853322,-14220951 ),
31+
new FieldElement( 4566830,-12963868,-28974889,-12240689,-7602672,-2830569,-8514358,-10431137,2207753,-3209784 )
32+
),
33+
new GroupElementPreComp(
34+
new FieldElement( -25154831,-4185821,29681144,7868801,-6854661,-9423865,-12437364,-663000,-31111463,-16132436 ),
35+
new FieldElement( 25576264,-2703214,7349804,-11814844,16472782,9300885,3844789,15725684,171356,6466918 ),
36+
new FieldElement( 23103977,13316479,9739013,-16149481,817875,-15038942,8965339,-14088058,-30714912,16193877 )
37+
),
38+
new GroupElementPreComp(
39+
new FieldElement( -33521811,3180713,-2394130,14003687,-16903474,-16270840,17238398,4729455,-18074513,9256800 ),
40+
new FieldElement( -25182317,-4174131,32336398,5036987,-21236817,11360617,22616405,9761698,-19827198,630305 ),
41+
new FieldElement( -13720693,2639453,-24237460,-7406481,9494427,-5774029,-6554551,-15960994,-2449256,-14291300 )
42+
),
43+
new GroupElementPreComp(
44+
new FieldElement( -3151181,-5046075,9282714,6866145,-31907062,-863023,-18940575,15033784,25105118,-7894876 ),
45+
new FieldElement( -24326370,15950226,-31801215,-14592823,-11662737,-5090925,1573892,-2625887,2198790,-15804619 ),
46+
new FieldElement( -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683 )
47+
)
48+
};
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System;
2+
using System.Security.Cryptography;
3+
4+
namespace Chaos.NaCl.Internal.Ed25519Ref10
5+
{
6+
internal static partial class Ed25519Operations
7+
{
8+
public static void crypto_sign_keypair(byte[] pk, int pkoffset, byte[] sk, int skoffset, byte[] seed, int seedoffset)
9+
{
10+
GroupElementP3 A;
11+
int i;
12+
13+
Array.Copy(seed, seedoffset, sk, skoffset, 32);
14+
#if NET5_0_OR_GREATER
15+
byte[] h = SHA512.HashData(sk.AsSpan(skoffset, 32));
16+
#else
17+
using var hash = SHA512.Create();
18+
byte[] h = hash.ComputeHash(sk, skoffset, 32);
19+
#endif
20+
ScalarOperations.sc_clamp(h, 0);
21+
22+
GroupOperations.ge_scalarmult_base(out A, h, 0);
23+
GroupOperations.ge_p3_tobytes(pk, pkoffset, ref A);
24+
25+
for (i = 0; i < 32; ++i) sk[skoffset + 32 + i] = pk[pkoffset + i];
26+
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER
27+
CryptographicOperations.ZeroMemory(h);
28+
#else
29+
CryptoBytes.Wipe(h);
30+
#endif
31+
}
32+
}
33+
}

0 commit comments

Comments
 (0)