Categories:
Audio (13)
Biotech (29)
Bytecode (36)
Database (77)
Framework (7)
Game (7)
General (507)
Graphics (53)
I/O (35)
IDE (2)
JAR Tools (101)
JavaBeans (21)
JDBC (121)
JDK (426)
JSP (20)
Logging (108)
Mail (58)
Messaging (8)
Network (84)
PDF (97)
Report (7)
Scripting (84)
Security (32)
Server (121)
Servlet (26)
SOAP (24)
Testing (54)
Web (15)
XML (309)
Collections:
Other Resources:
Source Code for Connector/J 8.0.31 - Core Impl
Where to get the Java source code for Connector/J 8.0 Core Impl module?
✍: FYIcenter.com
Java source code files for Connector/J 8.0 Core Impl module are:
⏎ com/mysql/cj/sasl/ScramShaSaslClient.java
/* * Copyright (c) 2020, 2022, Oracle and/or its affiliates. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License, version 2.0, as published by the * Free Software Foundation. * * This program is also distributed with certain software (including but not * limited to OpenSSL) that is licensed under separate terms, as designated in a * particular file or component or in included license documentation. The * authors of MySQL hereby grant you an additional permission to link the * program and your derivative works with the separately licensed software that * they have included with MySQL. * * Without limiting anything contained in the foregoing, this file, which is * part of MySQL Connector/J, is also subject to the Universal FOSS Exception, * version 1.0, a copy of which can be found at * http://oss.oracle.com/licenses/universal-foss-exception. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, * for more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package com.mysql.cj.sasl; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.SecureRandom; import java.util.Base64; import java.util.HashMap; import java.util.Map; import java.util.Random; import javax.security.sasl.SaslClient; import javax.security.sasl.SaslException; import com.mysql.cj.util.SaslPrep; import com.mysql.cj.util.SaslPrep.StringType; import com.mysql.cj.util.StringUtils; /** * A {@link SaslClient} implementation for SCRAM-SHA mechanisms as specified in <a href="https://tools.ietf.org/html/rfc5802">RFC 5802</a>. * Subclasses of this class must implement the hashing algorithms for the corresponding authentication mechanism. */ public abstract class ScramShaSaslClient implements SaslClient { protected enum ScramExchangeStage { TERMINATED(null), SERVER_FINAL(TERMINATED), SERVER_FIRST_CLIENT_FINAL(SERVER_FINAL), CLIENT_FIRST(SERVER_FIRST_CLIENT_FINAL); private ScramExchangeStage next; private ScramExchangeStage(ScramExchangeStage next) { this.next = next; } public ScramExchangeStage getNext() { return this.next == null ? this : this.next; } } protected static final int MINIMUM_ITERATIONS = 4096; protected static final String GS2_CBIND_FLAG = "n"; protected static final byte[] CLIENT_KEY = "Client Key".getBytes(); protected static final byte[] SERVER_KEY = "Server Key".getBytes(); protected String authorizationId; protected String authenticationId; protected String password; protected ScramExchangeStage scramStage = ScramExchangeStage.CLIENT_FIRST; protected String cNonce; protected String gs2Header; protected String clientFirstMessageBare; protected byte[] serverSignature; public ScramShaSaslClient(String authorizationId, String authenticationId, String password) throws SaslException { this.authorizationId = StringUtils.isNullOrEmpty(authorizationId) ? "" : authorizationId; this.authenticationId = StringUtils.isNullOrEmpty(authenticationId) ? this.authorizationId : authenticationId; if (StringUtils.isNullOrEmpty(this.authenticationId)) { throw new SaslException("The authenticationId cannot be null or empty."); } this.password = StringUtils.isNullOrEmpty(password) ? "" : password; this.scramStage = ScramExchangeStage.CLIENT_FIRST; } /** * Returns the real IANA-registered mechanism name of this SASL client. This is the same as {@link SaslClient#getMechanismName()} except that subclasses may * use custom mechanism names to avoid future name clashes. * * @return * a non-null string representing the IANA-registered mechanism name. */ abstract String getIanaMechanismName(); @Override public boolean hasInitialResponse() { return true; } @Override public byte[] evaluateChallenge(byte[] challenge) throws SaslException { try { switch (this.scramStage) { case CLIENT_FIRST: // Process client-first-message. // client-first-message = gs2-header client-first-message-bare // gs2-header = gs2-cbind-flag "," [ authzid ] "," // gs2-cbind-flag = "n" // authzid = "a=" saslname // client-first-message-bare = username "," nonce // username = "n=" saslname // saslname = 1*(value-safe-char / "=2C" / "=3D") // value-safe-char = UTF8 // ;; UTF8 except NUL, "=", and ",". // nonce = "r=" c-nonce [s-nonce] // ;; Second part provided by server. // c-nonce = printable // printable = %x21-2B / %x2D-7E // ;; Printable ASCII except ",". this.gs2Header = GS2_CBIND_FLAG + "," + (StringUtils.isNullOrEmpty(this.authorizationId) ? "" : "a=" + prepUserName(this.authorizationId)) + ","; this.cNonce = generateRandomPrintableAsciiString(32); this.clientFirstMessageBare = "n=" + prepUserName(this.authenticationId) + ",r=" + this.cNonce; String clientFirstMessage = this.gs2Header + this.clientFirstMessageBare; return StringUtils.getBytes(clientFirstMessage, "UTF-8"); case SERVER_FIRST_CLIENT_FINAL: // Process server-first-message & client-final-message. // 1st part: server-first-message. String serverFirstMessage = StringUtils.toString(challenge, StandardCharsets.UTF_8); Map<String, String> serverFirstAttributes = parseChallenge(serverFirstMessage); if (!serverFirstAttributes.containsKey("r") || !serverFirstAttributes.containsKey("s") || !serverFirstAttributes.containsKey("i")) { throw new SaslException("Missing required SCRAM attribute from server first message."); } String sNonce = serverFirstAttributes.get("r"); if (!sNonce.startsWith(this.cNonce)) { throw new SaslException("Invalid server nonce for " + getIanaMechanismName() + " authentication."); } byte[] salt = Base64.getDecoder().decode(serverFirstAttributes.get("s")); int iterations = Integer.parseInt(serverFirstAttributes.get("i")); if (iterations < MINIMUM_ITERATIONS) { throw new SaslException("Announced " + getIanaMechanismName() + " iteration count is too low."); } // 2nd part: client-final-message. // client-final-message-without-proof = channel-binding "," nonce // channel-binding = "c=" base64 // ;; base64 encoding of cbind-input. // cbind-input = gs2-header String clientFinalMessageWithoutProof = "c=" + Base64.getEncoder().encodeToString(StringUtils.getBytes(this.gs2Header, "UTF-8")) + ",r=" + sNonce; // Compute ClientProof: // SaltedPassword := Hi(Normalize(password), salt, i) // ClientKey := HMAC(SaltedPassword, "Client Key") // StoredKey := H(ClientKey) // AuthMessage := client-first-message-bare + "," + server-first-message + "," + client-final-message-without-proof // ClientSignature := HMAC(StoredKey, AuthMessage) // ClientProof := ClientKey XOR ClientSignature byte[] saltedPassword = hi(SaslPrep.prepare(this.password, StringType.STORED), salt, iterations); byte[] clientKey = hmac(saltedPassword, CLIENT_KEY); byte[] storedKey = h(clientKey); String authMessage = this.clientFirstMessageBare + "," + serverFirstMessage + "," + clientFinalMessageWithoutProof; byte[] clientSignature = hmac(storedKey, StringUtils.getBytes(authMessage, "UTF-8")); byte[] clientProof = clientKey.clone(); xorInPlace(clientProof, clientSignature); // client-final-message = client-final-message-without-proof "," proof // proof = "p=" base64 String clientFinalMessage = clientFinalMessageWithoutProof + ",p=" + Base64.getEncoder().encodeToString(clientProof); // Compute ServerSignature (for future verification): // ServerKey := HMAC(SaltedPassword, "Server Key") // ServerSignature := HMAC(ServerKey, AuthMessage) byte[] serverKey = hmac(saltedPassword, SERVER_KEY); this.serverSignature = hmac(serverKey, StringUtils.getBytes(authMessage, "UTF-8")); return StringUtils.getBytes(clientFinalMessage, "UTF-8"); case SERVER_FINAL: // Process server-final-message. String serverFinalMessage = StringUtils.toString(challenge, "UTF-8"); Map<String, String> serverFinalAttributes = parseChallenge(serverFinalMessage); if (serverFinalAttributes.containsKey("e")) { throw new SaslException("Authentication failed due to server error '" + serverFinalAttributes.get("e") + "'."); } if (!serverFinalAttributes.containsKey("v")) { throw new SaslException("Missing required SCRAM attribute from server final message."); } // verifier = "v=" base64 // ;; base-64 encoded ServerSignature. byte[] verifier = Base64.getDecoder().decode(serverFinalAttributes.get("v")); if (!MessageDigest.isEqual(this.serverSignature, verifier)) { throw new SaslException(getIanaMechanismName() + " server signature could not be verified."); } break; default: throw new SaslException("Unexpected SCRAM authentication message."); } return null; } catch (Throwable e) { this.scramStage = ScramExchangeStage.TERMINATED; throw e; } finally { this.scramStage = this.scramStage.getNext(); } } @Override public boolean isComplete() { return this.scramStage == ScramExchangeStage.TERMINATED; } @Override public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException { throw new IllegalStateException("Integrity and/or privacy has not been negotiated."); } @Override public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException { throw new IllegalStateException("Integrity and/or privacy has not been negotiated."); } @Override public Object getNegotiatedProperty(String propName) { return null; } @Override public void dispose() throws SaslException { } private String prepUserName(String userName) { return SaslPrep.prepare(userName, StringType.QUERY).replace("=", "=2D").replace(",", "=2C"); } /** * Parses a SASL challenge. * * @param challenge * the server message (challenge) to parse. * @return * a {@link Map} with the key/value pairs obtained from the server challenge. */ private Map<String, String> parseChallenge(String challenge) { Map<String, String> attributesMap = new HashMap<>(); for (String attribute : challenge.split(",")) { String[] keyValue = attribute.split("=", 2); attributesMap.put(keyValue[0], keyValue[1]); } return attributesMap; } /** * Generates a RFC 5802 safe nonce: "a sequence of random printable ASCII characters excluding ','" * * @param length * the length of the nonce. * @return * a randomly generated string formed by printable ASCII characters except comma. */ private String generateRandomPrintableAsciiString(int length) { final int first = 0x21; // First printable ASCII character: exclamation mark (!). final int last = 0x7E; // Last printable ASCII character: tilde (~). final int excl = 0x2C; // Comma (,) is excluded as per RFC 5802 (https://tools.ietf.org/html/rfc5802#section-5.1). final int bound = last - first; Random random = new SecureRandom(); char[] result = new char[length]; for (int i = 0; i < length;) { int randomValue = random.nextInt(bound) + first; if (randomValue != excl) { result[i++] = (char) randomValue; } } return new String(result); } /** * The "H(str)" cryptographic hash function as described in <a href="https://tools.ietf.org/html/rfc5802#section-2.2">RFC 5802, Section 2.2</a>. * * @param str * the string to hash. * @return * the hash value of the given string. */ abstract byte[] h(byte[] str); /** * The "HMAC(key, str)" HMAC keyed hash algorithm as described in <a href="https://tools.ietf.org/html/rfc5802#section-2.2">RFC 5802, Section 2.2</a>. * * @param key * the hash key. * @param str * the input string. * @return * the hashed value of the given params. */ abstract byte[] hmac(byte[] key, byte[] str); /** * The "Hi(str, salt, i)" PBKDF2 function as described in <a href="https://tools.ietf.org/html/rfc5802#section-2.2">RFC 5802, Section 2.2</a>. * * @param str * the string value to use as the internal HMAC key. * @param salt * the input string to hash in the initial iteration. * @param iterations * the number of iterations to run the algorithm. * * @return * an hash value with an output length equal to the length of H(str). */ abstract byte[] hi(String str, byte[] salt, int iterations); /** * Combines the two byte arrays in a XOR operation, changing the contents of the first. * * @param inOut * the left operand of the XOR operation and the destination of the result. * @param other * the right operand of the XOR operation. * @return * the same as the param <code>inOut</code>, after being updated. */ byte[] xorInPlace(byte[] inOut, byte[] other) { for (int i = 0; i < inOut.length; i++) { inOut[i] ^= other[i]; } return inOut; } }
⏎ com/mysql/cj/sasl/ScramShaSaslClient.java
Or download all of them as a single archive file:
File name: mysql-connector-java-core-impl-8.0.31.zip File size: 201048 bytes Release date: 2022-09-03 Download
⇒ Source Code for Connector/J 8.0.31 - Protocol Impl
⇐ Source Code for Connector/J 8.0.31 - Core API
2023-05-31, 11845👍, 0💬
Popular Posts:
What JAR files are required to run sax\Writer.java provided in the Apache Xerces package? 1 JAR file...
JDK 17 jdk.localedata.jmod is the JMOD file for JDK 17 Localedata module. JDK 17 Locale Data module ...
JDK 11 jdk.jdeps.jmod is the JMOD file for JDK 11 JDeps tool, which can be invoked by the "jdeps" co...
JDK 11 jdk.jlink.jmod is the JMOD file for JDK 11 JLink tool, which can be invoked by the "jlink" co...
What is ojdbc.jar - JDBC Driver for Oracle? ojdbc.jar is a JDBC driver from Oracle that provides dat...