最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

mysql协议的认证包及代码详情介绍

来源:动视网 责编:小采 时间:2020-11-09 09:09:06
文档

mysql协议的认证包及代码详情介绍

mysql协议的认证包及代码详情介绍:githttps://github.com/sea-boat/mysql-protocol概况mysql客户端登陆到mysql服务端需要一个交互的过程,首先服务端给客户端发送的初始握手包,客户端接收到握手包后向服务端返回认证包。如下,这里分析下认证包。client server |------
推荐度:
导读mysql协议的认证包及代码详情介绍:githttps://github.com/sea-boat/mysql-protocol概况mysql客户端登陆到mysql服务端需要一个交互的过程,首先服务端给客户端发送的初始握手包,客户端接收到握手包后向服务端返回认证包。如下,这里分析下认证包。client server |------


git

https://github.com/sea-boat/mysql-protocol

概况

mysql客户端登陆到mysql服务端需要一个交互的过程,首先服务端给客户端发送的初始握手包,客户端接收到握手包后向服务端返回认证包。如下,这里分析下认证包。

client server
 |-------connect------>|
 | |
 |<-----handshake------|
 | |
 |---authentication--->|
 | |

mysql通信报文结构

Payload认证包

4 capability flags, CLIENT_PROTOCOL_41 always set
4 max-packet size
1 character set
string[23] reserved (all [0])
string[NUL] username
 if capabilities & CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA {
lenenc-int length of auth-response
string[n] auth-response
 } else if capabilities & CLIENT_SECURE_CONNECTION {
1 length of auth-response
string[n] auth-response
 } else {
string[NUL] auth-response
 }
 if capabilities & CLIENT_CONNECT_WITH_DB {
string[NUL] database
 }
 if capabilities & CLIENT_PLUGIN_AUTH {
string[NUL] auth plugin name
 }
 if capabilities & CLIENT_CONNECT_ATTRS {
lenenc-int length of all key-values
lenenc-str key
lenenc-str value
 if-more data in 'length of all key-values', more keys and value pairs
 }

更多详情 : http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse

认证包操作

1.认证包类

/**
 * 
 * @author seaboat
 * @date 2016-09-25
 * @version 1.0
 * <pre><b>email: </b>849586227@qq.com</pre>
 * <pre><b>blog: </b>http://www.gxlcms.com/;/pre>
 * <p>mysql auth packet.</p>
 */public class AuthPacket extends MySQLPacket {
 private static final byte[] FILLER = new byte[23]; 
 public long clientFlags; 
 public long maxPacketSize; 
 public int charsetIndex; 
 public byte[] extra; 
 public String user; 
 public byte[] password; 
 public String database; 
 public void read(byte[] data) {
 MySQLMessage mm = new MySQLMessage(data);
 packetLength = mm.readUB3();
 packetId = mm.read();
 clientFlags = mm.readUB4();
 maxPacketSize = mm.readUB4();
 charsetIndex = (mm.read() & 0xff); 
 int current = mm.position(); 
 int len = (int) mm.readLength(); 
 if (len > 0 && len < FILLER.length) { 
 byte[] ab = new byte[len];
 System.arraycopy(mm.bytes(), mm.position(), ab, 0, len); 
 this.extra = ab;
 }
 mm.position(current + FILLER.length);
 user = mm.readStringWithNull();
 password = mm.readBytesWithLength(); 
 if (((clientFlags & Capabilities.CLIENT_CONNECT_WITH_DB) != 0)
 && mm.hasRemaining()) {
 database = mm.readStringWithNull();
 }
 } public void write(ByteBuffer buffer) throws IOException {
 BufferUtil.writeUB3(buffer, calcPacketSize());
 buffer.put(packetId);
 BufferUtil.writeUB4(buffer, clientFlags);
 BufferUtil.writeUB4(buffer, maxPacketSize);
 buffer.put((byte) charsetIndex);
 buffer.put(FILLER); if (user == null) {
 buffer.put((byte) 0);
 } else {
 BufferUtil.writeWithNull(buffer, user.getBytes());
 } if (password == null) {
 buffer.put((byte) 0);
 } else {
 BufferUtil.writeWithLength(buffer, password);
 } if (database == null) {
 buffer.put((byte) 0);
 } else {
 BufferUtil.writeWithNull(buffer, database.getBytes());
 }
 } @Override
 public int calcPacketSize() { 
 int size = 32;// 4+4+1+23;
 size += (user == null) ? 1 : user.length() + 1;
 size += (password == null) ? 1 : BufferUtil.getLength(password);
 size += (database == null) ? 1 : database.length() + 1; 
 return size;
 } @Override
 protected String getPacketInfo() { 
 return "MySQL Authentication Packet";
 }

}
  1. 加解密工具

/**
 * 
 * @author seaboat
 * @date 2016-09-25
 * @version 1.0
 * <pre><b>email: </b>849586227@qq.com</pre>
 * <pre><b>blog: </b>http://www.gxlcms.com/;/pre>
 * <p>a security util .</p>
 */public class SecurityUtil {

 public static final byte[] scramble411(byte[] pass, byte[] seed) 
 throws NoSuchAlgorithmException {
 MessageDigest md = MessageDigest.getInstance("SHA-1"); 
 byte[] pass1 = md.digest(pass);
 md.reset(); 
 byte[] pass2 = md.digest(pass1);
 md.reset();
 md.update(seed); 
 byte[] pass3 = md.digest(pass2); 
 for (int i = 0; i < pass3.length; i++) {
 pass3[i] = (byte) (pass3[i] ^ pass1[i]);
 } return pass3;
 } public static final String scramble323(String pass, String seed) { 
 if ((pass == null) || (pass.length() == 0)) { 
 return pass;
 } 
 byte b; 
 double d; 
 long[] pw = hash(seed); 
 long[] msg = hash(pass); 
 long max = 0x3fffffffL; 
 long seed1 = (pw[0] ^ msg[0]) % max; 
 long seed2 = (pw[1] ^ msg[1]) % max; 
 char[] chars = new char[seed.length()]; 
 for (int i = 0; i < seed.length(); i++) {
 seed1 = ((seed1 * 3) + seed2) % max;
 seed2 = (seed1 + seed2 + 33) % max;
 d = (double) seed1 / (double) max;
 b = (byte) java.lang.Math.floor((d * 31) + );
 chars[i] = (char) b;
 }
 seed1 = ((seed1 * 3) + seed2) % max;
 seed2 = (seed1 + seed2 + 33) % max;
 d = (double) seed1 / (double) max;
 b = (byte) java.lang.Math.floor(d * 31); 
 for (int i = 0; i < seed.length(); i++) {
 chars[i] ^= (char) b;
 } return new String(chars);
 } private static long[] hash(String src) { 
 long nr = 1345345333L; 
 long add = 7; 
 long nr2 = 0x12345671L; 
 long tmp; 
 for (int i = 0; i < src.length(); ++i) { 
 switch (src.charAt(i)) { 
 case ' ': 
 case '\t': 
 continue; 
 default:
 tmp = (0xff & src.charAt(i));
 nr ^= ((((nr & 63) + add) * tmp) + (nr << 8));
 nr2 += ((nr2 << 8) ^ nr);
 add += tmp;
 }
 } 
 long[] result = new long[2];
 result[0] = nr & 0x7fffffffL;
 result[1] = nr2 & 0x7fffffffL; 
 return result;
 }

}
  1. 测试类

/**
 * 
 * @author seaboat
 * @date 2016-09-25
 * @version 1.0
 * <pre><b>email: </b>849586227@qq.com</pre>
 * <pre><b>blog: </b>http://www.gxlcms.com/;/pre>
 * <p>test auth packet.</p>
 */public class AuthPacketTest {
 @Test
 public void produce() { 
 // handshake packet's rand1 and rand2
 byte[] rand1 = RandomUtil.randomBytes(8); 
 byte[] rand2 = RandomUtil.randomBytes(12); 
 byte[] seed = new byte[rand1.length + rand2.length];
 System.arraycopy(rand1, 0, seed, 0, rand1.length);
 System.arraycopy(rand2, 0, seed, rand1.length, rand2.length);

 AuthPacket auth = new AuthPacket();
 auth.packetId = 0;
 auth.clientFlags = getClientCapabilities();
 auth.maxPacketSize = 1024 * 1024 * 16;
 auth.user = "seaboat"; try {
 auth.password = SecurityUtil
 .scramble411("seaboat".getBytes(), seed);
 } catch (NoSuchAlgorithmException e) {
 e.printStackTrace();
 }
 auth.database = "test";

 ByteBuffer buffer = ByteBuffer.allocate(256);
 auth.write(buffer);
 buffer.flip(); byte[] bytes = new byte[buffer.remaining()];
 buffer.get(bytes, 0, bytes.length);
 String result = HexUtil.Bytes2HexString(bytes);
 System.out.println(result);
 assertTrue(Integer.valueOf(result.substring(0, 2), 16) == result
 .length() / 2 - 4);

 AuthPacket auth2 = new AuthPacket();
 auth2.read(bytes);
 assertTrue(auth2.database.equals("test"));
 } protected int getClientCapabilities() { 
 int flag = 0;
 flag |= Capabilities.CLIENT_LONG_PASSWORD;
 flag |= Capabilities.CLIENT_FOUND_ROWS;
 flag |= Capabilities.CLIENT_LONG_FLAG;
 flag |= Capabilities.CLIENT_CONNECT_WITH_DB;
 flag |= Capabilities.CLIENT_ODBC;
 flag |= Capabilities.CLIENT_IGNORE_SPACE;
 flag |= Capabilities.CLIENT_PROTOCOL_41;
 flag |= Capabilities.CLIENT_INTERACTIVE;
 flag |= Capabilities.CLIENT_IGNORE_SIGPIPE;
 flag |= Capabilities.CLIENT_TRANSACTIONS;
 flag |= Capabilities.CLIENT_SECURE_CONNECTION; 
 return flag;
 }
}

文档

mysql协议的认证包及代码详情介绍

mysql协议的认证包及代码详情介绍:githttps://github.com/sea-boat/mysql-protocol概况mysql客户端登陆到mysql服务端需要一个交互的过程,首先服务端给客户端发送的初始握手包,客户端接收到握手包后向服务端返回认证包。如下,这里分析下认证包。client server |------
推荐度:
标签: 协议 认证 mysql
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top