Skip to content

Commit 06f7b3d

Browse files
committed
Added xor as part of rsa encryption
Signed-off-by: S V <vats02581@gmail.com>
1 parent 0ded89c commit 06f7b3d

File tree

5 files changed

+72
-5
lines changed

5 files changed

+72
-5
lines changed

r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/InitFlow.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,7 @@ private AuthResponse createAuthResponse(String phase) {
615615
if (serverRSAPublicKeyFile != null && sslMode.equals(SslMode.DISABLED)) {
616616
return new AuthResponse(MySqlAuthProvider.rsaEncryption(authProvider.authentication(
617617
password, salt, client.getContext().getClientCollation()), serverRSAPublicKeyFile,
618-
client.getContext().getServerVersion()));
618+
client.getContext().getServerVersion(), salt));
619619
}
620620
throw new R2dbcPermissionDeniedException(authFails(authProvider.getType(), phase), CLI_SPECIFIC);
621621
}
@@ -729,7 +729,7 @@ private HandshakeResponse createHandshakeResponse(Capability capability) {
729729

730730
if (authProvider.isSslNecessary() && !sslCompleted && sslMode.equals(SslMode.DISABLED)) {
731731
authorization = MySqlAuthProvider.rsaEncryption(authorization, serverRSAPublicKeyFile,
732-
client.getContext().getServerVersion());
732+
client.getContext().getServerVersion(), salt);
733733
}
734734

735735
String authType = authProvider.getType();

r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/MySqlConnectionFactoryProvider.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,8 +343,8 @@ public final class MySqlConnectionFactoryProvider implements ConnectionFactoryPr
343343

344344
/**
345345
* Option to configure the database server's RSA Public Key file path on the local system if RSA encryption
346-
* is desired such as when using caching_sha2_password authentication type while {@link SSLMode} is DISABLED. If
347-
* serverRSAPublicKeyFile not {@code null} and {@link SSLMode} is not DISABLED, SSL encryption takes precedence.
346+
* is desired such as when using caching_sha2_password authentication type while {@link io.asyncer.r2dbc.mysql.constant.SslMode} is DISABLED. If
347+
* serverRSAPublicKeyFile not {@code null} and {@link io.asyncer.r2dbc.mysql.constant.SslMode} is not DISABLED, SSL encryption takes precedence.
348348
*
349349
* @since 1.4.2
350350
*/

r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/authentication/AuthUtils.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,5 +113,15 @@ private static byte[] allBytesXor(byte[] left, byte[] right) {
113113
return left;
114114
}
115115

116+
static byte[] rotatingXor(byte[] password, byte[] seedBytes) {
117+
int seedLength = seedBytes.length;
118+
119+
for (int i = 0; i < password.length; i++) {
120+
password[i] ^= seedBytes[i % seedLength];
121+
}
122+
123+
return password;
124+
}
125+
116126
private AuthUtils() { }
117127
}

r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/authentication/MySqlAuthProvider.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,13 @@ static MySqlAuthProvider build(String type) {
148148
* @param bytesToEncrypt the data to encrypt
149149
* @param serverRSAPublicKeyFile the file path on the local system of the database server's RSA Public Key
150150
* @param serverVersion the version of the MySQL server
151+
* @param seed the seed bytes for rotating XOR obfuscation
151152
* @return the encrypted bytes
152153
*/
153-
static byte[] rsaEncryption(byte[] bytesToEncrypt, String serverRsaPublicKeyFile, ServerVersion serverVersion) {
154+
static byte[] rsaEncryption(byte[] bytesToEncrypt, String serverRsaPublicKeyFile, ServerVersion serverVersion, byte[] seed) {
154155
try {
156+
bytesToEncrypt = AuthUtils.rotatingXor(bytesToEncrypt, seed);
157+
155158
String key = new String(Files.readAllBytes(Paths.get(serverRsaPublicKeyFile)), Charset.defaultCharset());
156159

157160
String publicKeyPEM = key
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright 2025 asyncer.io projects
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.asyncer.r2dbc.mysql.authentication;
18+
19+
import org.junit.jupiter.api.Test;
20+
21+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
22+
23+
import java.security.NoSuchAlgorithmException;
24+
import java.security.SecureRandom;
25+
26+
/**
27+
* Unit tests for {@link AuthUtils}
28+
*/
29+
public class AuthUtilsTest {
30+
31+
static byte[] seedBytes;
32+
33+
static {
34+
try {
35+
seedBytes = generateSalt(20);
36+
} catch (NoSuchAlgorithmException e) {
37+
seedBytes = "random".getBytes();
38+
}
39+
}
40+
41+
@Test
42+
void rotatingXor() {
43+
byte[] password = "abc123".getBytes();
44+
45+
assertDoesNotThrow(() -> AuthUtils.rotatingXor(password, seedBytes));
46+
}
47+
48+
static byte[] generateSalt(int length) throws NoSuchAlgorithmException {
49+
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
50+
byte[] salt = new byte[length];
51+
sr.nextBytes(salt);
52+
return salt;
53+
}
54+
}

0 commit comments

Comments
 (0)