This is an automated email from the ASF dual-hosted git repository.

panjuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new a9f1a0b314d Add OpenGaussAuthenticator (#23827)
a9f1a0b314d is described below

commit a9f1a0b314d4d43b5b5f1763d33825f5b2c68595
Author: Liang Zhang <[email protected]>
AuthorDate: Mon Jan 30 13:36:02 2023 +0800

    Add OpenGaussAuthenticator (#23827)
---
 .../OpenGaussAuthenticationHandler.java            | 120 +++++++--------------
 .../authenticator/OpenGaussAuthenticator.java      |  26 +++++
 ...OpenGaussSCRAMSha256PasswordAuthenticator.java} |  86 ++-------------
 3 files changed, 76 insertions(+), 156 deletions(-)

diff --git 
a/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
 
b/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
index 72cf3077ddc..6c672a70006 100644
--- 
a/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
+++ 
b/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
@@ -17,7 +17,6 @@
 
 package org.apache.shardingsphere.proxy.frontend.opengauss.authentication;
 
-import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
@@ -33,6 +32,8 @@ import org.apache.shardingsphere.infra.metadata.user.Grantee;
 import org.apache.shardingsphere.infra.metadata.user.ShardingSphereUser;
 import 
org.apache.shardingsphere.infra.util.exception.ShardingSpherePreconditions;
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
+import 
org.apache.shardingsphere.proxy.frontend.opengauss.authentication.authenticator.OpenGaussAuthenticator;
+import 
org.apache.shardingsphere.proxy.frontend.opengauss.authentication.authenticator.OpenGaussSCRAMSha256PasswordAuthenticator;
 
 import javax.crypto.Mac;
 import javax.crypto.SecretKeyFactory;
@@ -40,10 +41,8 @@ import javax.crypto.spec.PBEKeySpec;
 import javax.crypto.spec.SecretKeySpec;
 import java.nio.charset.StandardCharsets;
 import java.security.InvalidKeyException;
-import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.spec.InvalidKeySpecException;
-import java.util.Arrays;
 import java.util.Locale;
 import java.util.Optional;
 
@@ -59,12 +58,8 @@ public final class OpenGaussAuthenticationHandler {
     
     private static final String HMAC_SHA256_ALGORITHM = "HmacSHA256";
     
-    private static final String SHA256_ALGORITHM = "SHA-256";
-    
     private static final String SERVER_KEY = "Server Key";
     
-    private static final String CLIENT_KEY = "Client Key";
-    
     /**
      * Calculate server signature.
      *
@@ -81,66 +76,6 @@ public final class OpenGaussAuthenticationHandler {
         return bytesToHexString(result);
     }
     
-    private static String bytesToHexString(final byte[] src) {
-        StringBuilder result = new StringBuilder();
-        for (byte each : src) {
-            String hex = Integer.toHexString(each & 255);
-            if (hex.length() < 2) {
-                result.append(0);
-            }
-            result.append(hex);
-        }
-        return result.toString();
-    }
-    
-    /**
-     * Login with SCRAM SHA-256 password.
-     *
-     * @param username username
-     * @param databaseName database name
-     * @param salt salt in hex string
-     * @param nonce nonce in hex string
-     * @param serverIteration server iteration
-     * @param passwordMessagePacket password message packet
-     */
-    public static void loginWithSCRAMSha256Password(final String username, 
final String databaseName, final String salt, final String nonce, final int 
serverIteration,
-                                                    final 
PostgreSQLPasswordMessagePacket passwordMessagePacket) {
-        
ShardingSpherePreconditions.checkState(Strings.isNullOrEmpty(databaseName) || 
ProxyContext.getInstance().databaseExists(databaseName), () -> new 
UnknownDatabaseException(databaseName));
-        AuthorityRule authorityRule = 
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getGlobalRuleMetaData().getSingleRule(AuthorityRule.class);
-        Grantee grantee = new Grantee(username, "%");
-        Optional<ShardingSphereUser> user = authorityRule.findUser(grantee);
-        ShardingSpherePreconditions.checkState(user.isPresent(), () -> new 
UnknownUsernameException(username));
-        ShardingSpherePreconditions.checkState(isPasswordRight(user.get(), new 
Object[]{passwordMessagePacket.getDigest(), salt, nonce, serverIteration}),
-                () -> new InvalidPasswordException(username));
-        ShardingSpherePreconditions.checkState(null == databaseName || new 
AuthorityChecker(authorityRule, grantee).isAuthorized(databaseName),
-                () -> new PrivilegeNotGrantedException(username, 
databaseName));
-    }
-    
-    private static boolean isPasswordRight(final ShardingSphereUser user, 
final Object[] args) {
-        String h3HexString = (String) args[0];
-        String salt = (String) args[1];
-        String nonce = (String) args[2];
-        int serverIteration = (int) args[3];
-        byte[] serverStoredKey = calculatedStoredKey(user.getPassword(), salt, 
serverIteration);
-        byte[] h3 = hexStringToBytes(h3HexString);
-        byte[] h2 = calculateH2(user.getPassword(), salt, nonce, 
serverIteration);
-        byte[] clientCalculatedStoredKey = sha256(xor(h3, h2));
-        return Arrays.equals(clientCalculatedStoredKey, serverStoredKey);
-    }
-    
-    private static byte[] calculatedStoredKey(final String password, final 
String salt, final int serverIteration) {
-        byte[] k = generateKFromPBKDF2(password, salt, serverIteration);
-        byte[] clientKey = getKeyFromHmac(k, CLIENT_KEY.getBytes());
-        return sha256(clientKey);
-    }
-    
-    private static byte[] calculateH2(final String password, final String 
salt, final String nonce, final int serverIteration) {
-        byte[] k = generateKFromPBKDF2(password, salt, serverIteration);
-        byte[] clientKey = getKeyFromHmac(k, CLIENT_KEY.getBytes());
-        byte[] storedKey = sha256(clientKey);
-        return getKeyFromHmac(storedKey, hexStringToBytes(nonce));
-    }
-    
     @SneakyThrows({NoSuchAlgorithmException.class, 
InvalidKeySpecException.class})
     private static byte[] generateKFromPBKDF2(final String password, final 
String saltString, final int serverIteration) {
         char[] chars = password.toCharArray();
@@ -169,13 +104,6 @@ public final class OpenGaussAuthenticationHandler {
         return (byte) "0123456789ABCDEF".indexOf(c);
     }
     
-    @SneakyThrows(NoSuchAlgorithmException.class)
-    private static byte[] sha256(final byte[] str) {
-        MessageDigest md = MessageDigest.getInstance(SHA256_ALGORITHM);
-        md.update(str);
-        return md.digest();
-    }
-    
     @SneakyThrows({NoSuchAlgorithmException.class, InvalidKeyException.class})
     private static byte[] getKeyFromHmac(final byte[] key, final byte[] data) {
         SecretKeySpec signingKey = new SecretKeySpec(key, 
HMAC_SHA256_ALGORITHM);
@@ -184,13 +112,43 @@ public final class OpenGaussAuthenticationHandler {
         return mac.doFinal(data);
     }
     
-    private static byte[] xor(final byte[] password1, final byte[] password2) {
-        Preconditions.checkArgument(password1.length == password2.length, "Xor 
values with different length");
-        int length = password1.length;
-        byte[] result = new byte[length];
-        for (int i = 0; i < length; i++) {
-            result[i] = (byte) (password1[i] ^ password2[i]);
+    private static String bytesToHexString(final byte[] src) {
+        StringBuilder result = new StringBuilder();
+        for (byte each : src) {
+            String hex = Integer.toHexString(each & 255);
+            if (hex.length() < 2) {
+                result.append(0);
+            }
+            result.append(hex);
         }
-        return result;
+        return result.toString();
+    }
+    
+    /**
+     * Login with SCRAM SHA-256 password.
+     *
+     * @param username username
+     * @param databaseName database name
+     * @param salt salt in hex string
+     * @param nonce nonce in hex string
+     * @param serverIteration server iteration
+     * @param passwordMessagePacket password message packet
+     */
+    public static void loginWithSCRAMSha256Password(final String username, 
final String databaseName, final String salt, final String nonce, final int 
serverIteration,
+                                                    final 
PostgreSQLPasswordMessagePacket passwordMessagePacket) {
+        
ShardingSpherePreconditions.checkState(Strings.isNullOrEmpty(databaseName) || 
ProxyContext.getInstance().databaseExists(databaseName), () -> new 
UnknownDatabaseException(databaseName));
+        AuthorityRule authorityRule = 
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getGlobalRuleMetaData().getSingleRule(AuthorityRule.class);
+        Grantee grantee = new Grantee(username, "%");
+        Optional<ShardingSphereUser> user = authorityRule.findUser(grantee);
+        ShardingSpherePreconditions.checkState(user.isPresent(), () -> new 
UnknownUsernameException(username));
+        
ShardingSpherePreconditions.checkState(getAuthenticator(grantee).authenticate(user.get(),
 new Object[]{passwordMessagePacket.getDigest(), salt, nonce, serverIteration}),
+                () -> new InvalidPasswordException(username));
+        ShardingSpherePreconditions.checkState(null == databaseName || new 
AuthorityChecker(authorityRule, grantee).isAuthorized(databaseName),
+                () -> new PrivilegeNotGrantedException(username, 
databaseName));
+    }
+    
+    private static OpenGaussAuthenticator getAuthenticator(final Grantee 
grantee) {
+        // TODO get authenticator by username and hostname
+        return new OpenGaussSCRAMSha256PasswordAuthenticator();
     }
 }
diff --git 
a/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/authenticator/OpenGaussAuthenticator.java
 
b/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/authenticator/OpenGaussAuthenticator.java
new file mode 100644
index 00000000000..c125e174435
--- /dev/null
+++ 
b/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/authenticator/OpenGaussAuthenticator.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package 
org.apache.shardingsphere.proxy.frontend.opengauss.authentication.authenticator;
+
+import org.apache.shardingsphere.proxy.frontend.authentication.Authenticator;
+
+/**
+ * OpenGauss authenticator.
+ */
+public interface OpenGaussAuthenticator extends Authenticator<Object[]> {
+}
diff --git 
a/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
 
b/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/authenticator/OpenGaussSCRAMSha256PasswordAuthenticator.java
similarity index 55%
copy from 
proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
copy to 
proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/authenticator/OpenGaussSCRAMSha256PasswordAuthenticator.java
index 72cf3077ddc..6556c946810 100644
--- 
a/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/OpenGaussAuthenticationHandler.java
+++ 
b/proxy/frontend/opengauss/src/main/java/org/apache/shardingsphere/proxy/frontend/opengauss/authentication/authenticator/OpenGaussSCRAMSha256PasswordAuthenticator.java
@@ -15,45 +15,28 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.proxy.frontend.opengauss.authentication;
+package 
org.apache.shardingsphere.proxy.frontend.opengauss.authentication.authenticator;
 
 import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
 import lombok.SneakyThrows;
-import org.apache.shardingsphere.authority.checker.AuthorityChecker;
-import org.apache.shardingsphere.authority.rule.AuthorityRule;
-import 
org.apache.shardingsphere.db.protocol.postgresql.packet.handshake.PostgreSQLPasswordMessagePacket;
-import 
org.apache.shardingsphere.dialect.exception.syntax.database.UnknownDatabaseException;
-import 
org.apache.shardingsphere.dialect.postgresql.exception.authority.InvalidPasswordException;
-import 
org.apache.shardingsphere.dialect.postgresql.exception.authority.PrivilegeNotGrantedException;
-import 
org.apache.shardingsphere.dialect.postgresql.exception.authority.UnknownUsernameException;
-import org.apache.shardingsphere.infra.metadata.user.Grantee;
+import 
org.apache.shardingsphere.db.protocol.postgresql.constant.PostgreSQLAuthenticationMethod;
 import org.apache.shardingsphere.infra.metadata.user.ShardingSphereUser;
-import 
org.apache.shardingsphere.infra.util.exception.ShardingSpherePreconditions;
-import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 
 import javax.crypto.Mac;
 import javax.crypto.SecretKeyFactory;
 import javax.crypto.spec.PBEKeySpec;
 import javax.crypto.spec.SecretKeySpec;
-import java.nio.charset.StandardCharsets;
 import java.security.InvalidKeyException;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.spec.InvalidKeySpecException;
 import java.util.Arrays;
 import java.util.Locale;
-import java.util.Optional;
 
 /**
- * Authentication handler for openGauss.
- * 
- * @see <a 
href="https://opengauss.org/zh/blogs/blogs.html?post/douxin/sm3_for_opengauss/";>SM3
 for openGauss</a>
+ * SCRAM Sha256 password authenticator for openGauss.
  */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class OpenGaussAuthenticationHandler {
+public final class OpenGaussSCRAMSha256PasswordAuthenticator implements 
OpenGaussAuthenticator {
     
     private static final String PBKDF2_WITH_HMAC_SHA1_ALGORITHM = 
"PBKDF2WithHmacSHA1";
     
@@ -61,62 +44,10 @@ public final class OpenGaussAuthenticationHandler {
     
     private static final String SHA256_ALGORITHM = "SHA-256";
     
-    private static final String SERVER_KEY = "Server Key";
-    
     private static final String CLIENT_KEY = "Client Key";
     
-    /**
-     * Calculate server signature.
-     *
-     * @param password password
-     * @param salt salt in hex string
-     * @param nonce nonce in hex string
-     * @param serverIteration server iteration
-     * @return server signature
-     */
-    public static String calculateServerSignature(final String password, final 
String salt, final String nonce, final int serverIteration) {
-        byte[] k = generateKFromPBKDF2(password, salt, serverIteration);
-        byte[] serverKey = getKeyFromHmac(k, 
SERVER_KEY.getBytes(StandardCharsets.UTF_8));
-        byte[] result = getKeyFromHmac(serverKey, hexStringToBytes(nonce));
-        return bytesToHexString(result);
-    }
-    
-    private static String bytesToHexString(final byte[] src) {
-        StringBuilder result = new StringBuilder();
-        for (byte each : src) {
-            String hex = Integer.toHexString(each & 255);
-            if (hex.length() < 2) {
-                result.append(0);
-            }
-            result.append(hex);
-        }
-        return result.toString();
-    }
-    
-    /**
-     * Login with SCRAM SHA-256 password.
-     *
-     * @param username username
-     * @param databaseName database name
-     * @param salt salt in hex string
-     * @param nonce nonce in hex string
-     * @param serverIteration server iteration
-     * @param passwordMessagePacket password message packet
-     */
-    public static void loginWithSCRAMSha256Password(final String username, 
final String databaseName, final String salt, final String nonce, final int 
serverIteration,
-                                                    final 
PostgreSQLPasswordMessagePacket passwordMessagePacket) {
-        
ShardingSpherePreconditions.checkState(Strings.isNullOrEmpty(databaseName) || 
ProxyContext.getInstance().databaseExists(databaseName), () -> new 
UnknownDatabaseException(databaseName));
-        AuthorityRule authorityRule = 
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getGlobalRuleMetaData().getSingleRule(AuthorityRule.class);
-        Grantee grantee = new Grantee(username, "%");
-        Optional<ShardingSphereUser> user = authorityRule.findUser(grantee);
-        ShardingSpherePreconditions.checkState(user.isPresent(), () -> new 
UnknownUsernameException(username));
-        ShardingSpherePreconditions.checkState(isPasswordRight(user.get(), new 
Object[]{passwordMessagePacket.getDigest(), salt, nonce, serverIteration}),
-                () -> new InvalidPasswordException(username));
-        ShardingSpherePreconditions.checkState(null == databaseName || new 
AuthorityChecker(authorityRule, grantee).isAuthorized(databaseName),
-                () -> new PrivilegeNotGrantedException(username, 
databaseName));
-    }
-    
-    private static boolean isPasswordRight(final ShardingSphereUser user, 
final Object[] args) {
+    @Override
+    public boolean authenticate(final ShardingSphereUser user, final Object[] 
args) {
         String h3HexString = (String) args[0];
         String salt = (String) args[1];
         String nonce = (String) args[2];
@@ -193,4 +124,9 @@ public final class OpenGaussAuthenticationHandler {
         }
         return result;
     }
+    
+    @Override
+    public String getAuthenticationMethodName() {
+        return PostgreSQLAuthenticationMethod.SCRAM_SHA256.getMethodName();
+    }
 }

Reply via email to