有时候大家会忘记WinSCP中保存的密码
下面用java提取WinSCP保存的密码
package com.sglyz.simple;
import java.util.*;
/**
* @author sg
*/
public class DecodeWinSCP {
public static final int PWALG_SIMPLE_FLAG = 0xFF;
public static final char PWALG_SIMPLE_MAGIC = 0xA3;
public static List<Character> fPassword = new ArrayList<>();
public static void main(String[] args) {
String hostName = "192.168.17.4";
String userName = "root";
String pwdStr =
"A35C4A5F0460782E3333286D656E726D6A64726D6B72686D6E6F68696A6D2AB3A5FE7044DCAE7B1BFA2896052D79D9C276B6";
Map<String, Object> result = getPassWord(hostName, userName, pwdStr);
System.out.println(result);
}
/**
* 获取密码
*
* @param hostName 用户名
* @param userName 主机名
* @param iniPwdStr WinSCP密码加密后的字符串
* @return
*/
public static Map<String, Object> getPassWord(
String hostName,
String userName,
String iniPwdStr
) {
for (int i = 0; i < iniPwdStr.length(); ++i) {
fPassword.add((char) Integer.parseInt("" + iniPwdStr.charAt(i), 16));
}
Map<String, Object> map = new LinkedHashMap<>();
String pwd = decryptPassword(fPassword, userName + hostName);
map.put("主机名", hostName);
map.put("用户名", userName);
map.put("密码", pwd);
return map;
}
/**
* 解密
*
* @param password
* @param unicodeKey
* @return
*/
private static String decryptPassword(
List<Character> password,
String unicodeKey
) {
String key = unicodeKey;
String result = "";
char length, flag;
flag = simpleDecryptNextChar(password);
if (flag == PWALG_SIMPLE_FLAG) {
/* Dummy = */
simpleDecryptNextChar(password);
length = simpleDecryptNextChar(password);
} else length = flag;
int newStart = ((int) simpleDecryptNextChar(password) * 2);
removeItems(password, 0, newStart);
for (int index = 0; index < length; ++index) result +=
simpleDecryptNextChar(password);
if (flag == PWALG_SIMPLE_FLAG) {
if (!result.substring(0, key.length()).equals(key)) result =
""; else result = result.substring(key.length());
}
return result;
}
/**
* unsigned char simpleDecryptNextChar(RawByteString &Str)
* {
* if (Str.Length() > 0)
* {
* unsigned char Result = (unsigned char)
* ~((((PWALG_SIMPLE_STRING.Pos(Str.c_str()[0])-1) << 4) +
* ((PWALG_SIMPLE_STRING.Pos(Str.c_str()[1])-1) << 0)) ^ PWALG_SIMPLE_MAGIC);
* Str.Delete(1, 2);
* return Result;
* }
* else return 0x00;
* }
*
* @param str
* @return
*/
private static char simpleDecryptNextChar(List<Character> str) {
if (str.size() > 0) {
char result = unsignedChar(
~(
(
unsignedChar(str.get(0) << 4) + str.get(1) // Remove bitshift overflow bits.
) ^
PWALG_SIMPLE_MAGIC
)
);
removeItems(str, 0, 2);
return result;
} else return 0x00;
}
/**
* Cut off anything over 255.
*
* @param v
* @return
*/
private static char unsignedChar(int v) {
return (char) (v & 0xFF);
}
/**
* Remove items from list
*/
private static void removeItems(List<Character> lst, int start, int end) {
for (int i = 0; i < end - start; ++i) {
lst.remove(start);
}
}
}