Java - Cannot encrypt Windows Remote Desktop password in RDP file

Go To StackoverFlow.com

2

I am trying to create an RDP file on a computer programmatically. I am taking the username and password from a PROPERTIES file, and trying to use CryptProtectData() to encrypt it to a vlaid format. I then generate the string password 51:b:<encrypted password> and store it in the .RDP file.

When I look in the RDP file, I get output similar to the following: password 51:b:[B@3fd83fd8

Looking here: http://www.remkoweijnen.nl/blog/2007/10/18/how-rdp-passwords-are-encrypted/ you can see that the password is not in the correct format.

By the way, in order to do the encrypting, I am using the import: import com.sun.jna.platform.win32.Crypt32Util; to access Crypt32Util.cryptProtectData(passwordBytes) as can be seen from this code:

FileWriter fstream = new FileWriter(rdpFile);
BufferedWriter out = new BufferedWriter(fstream);
out.write("full address:s:"+remoteServerIP);
out.write("\nusername:s:"+username);
byte[] passwordBytes = password.getBytes();
out.write("\npassword 51:b:"+Crypt32Util.cryptProtectData(passwordBytes));

I'd be grateful to anyone who can help me encrypt the password correctly.

Thank you.

PS, I'm using Windows XP

EDIT: I found this info on encrypting using C/C++, and I looked in wincrypt.h but I couldnt identify anything useful: http://blogs.msdn.com/b/rds/archive/2007/01/22/vista-remote-desktop-connection-authentication-faq.aspx

2012-04-04 19:58
by eoinzy
[B@something is Java's default toString() of a byte[] (the [B part) with the internal address of something. Whenever you see such a thing you should immediately be aware that you probably don't want to output it like this - Joey 2012-04-04 21:14
Thats true, but does that mean I'm using the wrong bytes? Or should the ToHexString method posted my @mazaneicha below still work - eoinzy 2012-04-04 21:35
It doesn't necessarily mean you're using the wrong bytes, it just means that you're not using the bytes but rather a string of meaningless junk. And it's helpful it you recognize it as such immediately - Joey 2012-04-05 05:08
OK I understand now. I'll try various methods to output the correct bytes for testing, so I'll know if I get [B@... then I'm doing it wrong - eoinzy 2012-04-06 16:39


2

By looking at your link, it seems that you're missing a step of converting the byte array (the result of applying CryptUtil to a password) into a hex-string representation:

out.write("\npassword 51:b:"+ ToHexString(Crypt32Util.cryptProtectData(passwordBytes)));

where ToHexString(byte[] barray):String can look something like this:

public static String ToHexString(byte[] bytes) {   
    StringBuilder sb = new StringBuilder();   
    Formatter formatter = new Formatter(sb);   
    for (byte b : bytes) {
        formatter.format("%02x", b);   
    }
    return sb.toString();   
}  
2012-04-04 20:54
by mazaneicha
Thanks for the reply! I've tried my code with your ToHexString and the RDP client now accepts the .RDP file. However, I get a popup saying that the password is wrong. Is it possible Crypt32Util is encoding wrong? Or could it be the hex conversion? The converted hex string is a lot shorter than the one provided in the link I posted originally - eoinzy 2012-04-04 21:37
Hi! in the article, they use some function -- BlobDataToHexStr(DataOut.pbData, DataOut.cbData) -- to perform the conversion. So its either this function does something special which I have no way of knowing, or CryptUtil isnt doing its job. You can also try to modify our ToHexString function by allocating sufficient StringBuilder upfront, like this: StringBuilder sb = new StringBuilder(2*bytes.length); ... Best of luck - mazaneicha 2012-04-04 21:58
For the record, the source of that, in Delphi, is here: http://www.cnblogs.com/devs/articles/2264812.htm - eoinzy 2012-04-04 22:29
I never managed to fix this in code. In the end I had to use an external .exe to encrpyt it for me. But since I don't need this anymore, I've just accepted this answer as its the only one - eoinzy 2012-06-01 17:43
The problem here is the missing encoding on passwordBytes array: passwordString.getBytes("UTF-16LE") will solve - Daniele Brugnara 2013-09-30 14:28


1

   String paasword ="pwd";
    DATA_BLOB pDataIn = new DATA_BLOB(password.getBytes(Charset.forName("UTF-16LE")));
    DATA_BLOB pDataEncrypted = new DATA_BLOB();
    System.out.println(Crypt32.INSTANCE.CryptProtectData(pDataIn, "psw", 
            null, null, null, WinCrypt.CRYPTPROTECT_UI_FORBIDDEN, pDataEncrypted));
   StringBuffer epwsb = new StringBuffer();
   byte[] pwdBytes= new byte [pDataEncrypted.cbData];      
   pwdBytes=pDataEncrypted.getData();
    Formatter formatter = new Formatter(epwsb);
     for ( final byte b : pwdBytes ) {
    formatter.format("%02X", b);
         }
  System.out.println("password 51:b:"+ epwsb.toString());
2013-06-13 09:04
by كريم الجبالي


1

Here's my working solution (you need JNA platform, to get this working):

    private static String ToHexString(byte[] bytes) {   
        StringBuilder sb = new StringBuilder();   
        Formatter formatter = new Formatter(sb);   
        for (byte b : bytes) {
            formatter.format("%02x", b);   
        }
        formatter.close();
        return sb.toString();   
    }  

    private String cryptRdpPassword(String pass) {
        try {
            return ToHexString(Crypt32Util.cryptProtectData(pass.getBytes("UTF-16LE"), null, 0, "psw", null));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return "ERROR";
        }
    }
2013-09-27 08:16
by Daniele Brugnara
thx a lot! it is working - user1043173 2014-01-16 07:16
@user1043173: remember that the encrypted password will work only from the computer who generated - Daniele Brugnara 2014-01-16 07:30


0

I just found a way to solute this problem yestoday.It was wrong just because of the difference between windows(c++) and java. I can encypt the password and autofill it in the rdpfile,and login in the remote desktop without filling the password again.

2012-08-16 02:39
by withnate
How did u fix it? Any source code - eoinzy 2012-08-21 09:12
please, share how you did : - Daniele Brugnara 2013-09-20 09:03
the java is big-endian,but c++ on windows is little-endian.transform the bytes ,you will get the right access - withnate 2016-09-22 10:43
Ads