1
\$\begingroup\$

I have a program that makes a call to an SQL database. I cannot use SSH to connect to it (as far as I am aware) or any other more secure method, so Java's SQL connector was used. As the connection requires a username/password, and I want to store the user/pass for ease of making the connection. I knew I was not going to store the password in plain text, but I couldn't find a method of doing so in a secure manner in a platform-independent way in core Java, so I rolled my own (not advised in crypto, I know).

Below is the code that encrypts a message of any length with a key of any length.

private static String xor(String message, String key){
    if(message.isEmpty())
        return "";
    byte[] xorBlob=new byte[message.length()];
    long seed=0;
    for(char c: key.toCharArray())
        seed+=c;
    new Random(seed).nextBytes(xorBlob);
    char[] mArr=message.toCharArray();
    for(int i=0;i<mArr.length;i++)
        mArr[i]=(char)(mArr[i]^xorBlob[i]);
    return new String(mArr);
}

To put the above code into words: It sums up all the char values of the given key into an int. That int is then used as the seed for the Random function, which then spits out an array of bytes the length of the message. The message and that byte array are then xor'd together.

It's rudimentary, but I figured for opt-in local storage of a password for the current user, it should suffice.

Is this a good method of doing so? Is there a way I can improve this code, for either more security or just better code to more fit industry standards?

EDIT: Here's the code that calls the above function:

FileWriter writer=new FileWriter(config);
writer.write(String.format("username=%s%n", username));
writer.write(String.format("password=%s%n", xor(password, username)));
\$\endgroup\$
  • 1
    \$\begingroup\$ To get a better review you post the code that uses this as well. \$\endgroup\$ – pacmaninbw Jun 26 at 14:32
  • \$\begingroup\$ @pacmaninbw Sure, I can add that, but it's a single line. \$\endgroup\$ – Zly Martin Jun 26 at 14:46
  • \$\begingroup\$ I guess I wasn't all that clear, how about the entire class. \$\endgroup\$ – pacmaninbw Jun 26 at 14:48
  • \$\begingroup\$ @pacmaninbw No I cannot do that. I also do not see how that would help, as I'm asking for this method in particular. The surrounding class just reads/writes data to a file. This method is called twice, once to encrypt the password and once to decrypt it. \$\endgroup\$ – Zly Martin Jun 26 at 14:58
  • \$\begingroup\$ Basically, we only have to guess a small number (the sum of letters) in order to break this key. Assuming that the password contains a–zA–Z0–9 characters and has N size, we can break the key in 62*N attempts at max, while it would take ut to 62^N attempts to guess the password!! So this is a really weak KDF and it significantly reduces the strength of your password. The simplest (but least preferable) KDF is PBKDF1, which just uses a hash in a loop. It is very easy to implement but it requires a hash function. \$\endgroup\$ – t.m.adam Jun 26 at 19:08
0
\$\begingroup\$

As you stated, you probably shouldn't roll your own. Have you considered using a key vault?

https://www.vaultproject.io/

\$\endgroup\$
  • \$\begingroup\$ The linked "vaultproject" seems like a centralized secret manager? That goes way and beyond the needs here. Seems akin to replacing batteries with a connection directly to mains, if you don't mind the electrician analogy. This program just needs to somewhat secure a user's password for them on their local machine as the program is also running locally. It just makes a couple DB calls when it needs to, on the one connection made using the password. An enterprise-level key vault seems overkill. \$\endgroup\$ – Zly Martin Jun 26 at 15:28
  • 2
    \$\begingroup\$ Nah, using off-the-shelf software isn't overkill. It's completely secure and requires practically no maintenance. You can't say that same about stuff you roll for yourself! What are you trying to conserve by not using COTS? \$\endgroup\$ – Slothario Jun 26 at 15:36
  • \$\begingroup\$ I don't need, or want, a central collection of this information. It should only be storing the local computer user's credentials locally. This is in a business environment as well, maybe I should add that to the question. But this is a locally-ran program connecting to a DB on the network. It just seems like, by using the "vaultproject" or similar vaults that, even though it is likely lightyears ahead of anything I could roll myself, it's way ridiculous for the small projects this would be a part of. 1/2 \$\endgroup\$ – Zly Martin Jun 26 at 15:47
  • \$\begingroup\$ The only thing I'm trying to conserve here is scope. I'd need a server, licenses (maybe?), recode the function into making all these other types of calls, add many LOCs to this, but would also aggregate all the user/pass of the people that may use this program. 2/2 \$\endgroup\$ – Zly Martin Jun 26 at 15:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.