windows远程连接的文件(mstsc)是RDP格式的,通过RDP文件我们可以实现直接连接,不需要输入密码等信息,打开及连。RDP中的密码加密不是常规的加密方式,但是微软在WinAPI中开放出了加密解密函数。我比较熟悉java,就采用java实现以下RDP的加密解密。

1.准备

因为是WinAPI里面的东西,java访问使用jna是很好的选择。

pom.xml:

1
2
3
4
5
6
7
8
9
10
11
12
<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>4.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna-platform -->
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>4.0.0</version>
</dependency>

2.代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

import com.sun.jna.platform.win32.Crypt32;
import com.sun.jna.platform.win32.Crypt32Util;
import com.sun.jna.platform.win32.WinCrypt;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Formatter;

/**
* @Description:
* @ClassName:RDPCompile
* @Author:Player
* @Date:2019-04-15 15:51
**/
public class RDPCompile {
public static void main(String[] args) {

String password = "Player";

/*加密*/
String compilePassword = cryptRdpPassword0(password);
System.out.println("加密:" + compilePassword);


/*解密*/
String originalPassword = DecodeRdpPassword(compilePassword);
System.out.println("解密:" + originalPassword);


}


/*执行加密*/
private static String cryptRdpPassword0(String password) {
WinCrypt.DATA_BLOB pDataIn = new WinCrypt.DATA_BLOB(password.getBytes(Charset.forName("UTF-16LE")));
WinCrypt.DATA_BLOB pDataEncrypted = new WinCrypt.DATA_BLOB();
Crypt32.INSTANCE.CryptProtectData(pDataIn, "psw", null, null, null, 1, pDataEncrypted);
StringBuffer epwsb = new StringBuffer();
byte[] pwdBytes;
pwdBytes = pDataEncrypted.getData();
Formatter formatter = new Formatter(epwsb);
for (final byte b : pwdBytes) {
formatter.format("%02X", b);
}
return epwsb.toString();
}


/*执行解密*/
private static String DecodeRdpPassword(String password) {
try {
return new String(Crypt32Util.cryptUnprotectData(toBytes(password)), StandardCharsets.UTF_16LE);
} catch (Exception e1) {
e1.printStackTrace();
return "ERROR";
}
}

/*去掉0x以后,转整数再转型成字节*/
private static byte[] toBytes(String str) {
if (str == null || str.trim().equals("")) {
return new byte[0];
}
byte[] bytes = new byte[str.length() / 2];
for (int i = 0; i < str.length() / 2; i++) {
String subStr = str.substring(i * 2, i * 2 + 2);
bytes[i] = (byte) Integer.parseInt(subStr, 16);
}
return bytes;
}

}