Protect embedded password - java

I have a properties file in java, in which I store all information of my app, like logo image filename, database name, database user and database password.
I can store the password encrypted on the properties file. But, the key or passphrase can be read out of the jar using a decompiler.
Is there a way to store the db pass in a properties file securely?

There are multiple ways to manage this. If you can figure out a way to have a user provide a password for a keystore when the application starts up the most appropriate way would be to encrypt all the values using a key, and store this key in the keystore. The command line interface to the keystore is by using keytool. However JSE has APIs to programmatically access the keystore as well.
If you do not have an ability to have a user manually provide a password to the keystore on startup (say for a web application), one way to do it is to write an exceptionally complex obfuscation routine which can obfuscate the key and store it in a property file as well. Important things to remember is that the obfuscation and deobfuscation logic should be multi layered (could involve scrambling, encoding, introduction of spurious characters etc. etc.) and should itself have at least one key which could be hidden away in other classes in the application using non intuitive names. This is not a fully safe mechanism since someone with a decompiler and a fair amount of time and intelligence can still work around it but is the only one I know of which does not require you to break into native (ie. non easily decompilable) code.

You store a SHA1 hash of the password in your properties file. Then when you validate a users password, you hash their login attempt and make sure that the two hashes match.
This is the code that will hash some bytes for you. You can easily ger bytes from a String using the getBytes() method.
/**
* Returns the hash value of the given chars
*
* Uses the default hash algorithm described above
*
* #param in
* the byte[] to hash
* #return a byte[] of hashed values
*/
public static byte[] getHashedBytes(byte[] in)
{
MessageDigest msg;
try
{
msg = MessageDigest.getInstance(hashingAlgorithmUsed);
}
catch (NoSuchAlgorithmException e)
{
throw new AssertionError("Someone chose to use a hashing algorithm that doesn't exist. Epic fail, go change it in the Util file. SHA(1) or MD5");
}
msg.update(in);
return msg.digest();
}

No there is not. Even if you encrypt it, somebody will decompile the code that decrypts it.

You could make a separate properties file (outside the jar) for passwords (either direct DB password or or key passphrase) and not include that properties file with the distribution. Or you might be able to make the server only accept that login from a specific machine so that spoofing would be required.

In addition to encrypting the passwords as described above put any passwords in separate properties file and on deployment try to give this file the most locked down permissions possible.
For example, if your Application Server runs on Linux/Unix as root then make the password properties file owned by root with 400/-r-------- permissions.

Couldn't you have the app contact a server over https and download the password, after authenticating in some way of course?

Related

Encrypt user passwords when uploading code and decrypt during run-time

Have to begin moving in-house, local machine only Java framework into a private but online repo for staff only, however, the current framework requires a properties class which includes sensitive information (usernames, passwords etc) to login to the database and other technology the framework uses.
As a result, pushing the latest framework will include all of said individuals usernames/passwords, which is a security concern.
I've been asked to "Encrypt the password so when it's uploaded it's hidden" and then "Decrypt the password during runtime, so that information can be used to execute the code, as without the login data, the framework will not work".
While there is much better solutions (ie just don't upload the properties class, rework framework to not need the properties class etc), this is apparently unacceptable as it "works this way".
I'm struggling on the logic of this request, but furthermore how this task could actually be accomplished.
There's a few solutions I pinged about having it in a private notepad on your system only, but again apparently unacceptable.
It "needs to just be within a new Java Class".
Is this request possible, and if so, what sort of approach could I take? So the sensitive information within the properties class is encrypted if someone downloads the framework, but when executed, that information is decrypted and the framework runs. Framework is being uploaded to Bitbucket.
(Not asking for the code, just asking for help working out how this could be achieved, if at all, because it seems to be a very strange request or am I missing something?)
Here is the snippet to upload your data to the server. os must be a valid output stream used for upload.
OutputStream os = ... /* your upload stream */
OutputStream gzipos = new GZIPOutputStream(os);
CryptoAlgorithm = "RSA";
Cipher cipher = Cipher.getInstance(CryptoAlgorithm);
cipher.init(Cipher.ENCRYPT_MODE, PuK);
CipherOutputStream cos = new CipherOutputStream(gzipos, cipher);
DataOutputStream dos = new DataOutputStream(cos);
dos.write... /* use it as a normal data output stram /*
I use DataOutputStream because I used binary data in my implementation. Still, you can also use a normal writer:
Writer w = new OutputStreamWriter(cos);
And, for the download snippet:
CryptoAlgorithm = "RSA";
...
Cipher cipher = Cipher.getInstance(CryptoAlgorithm);
cipher.init(Cipher.DECRYPT_MODE, PK);
CipherInputStream cis = new CipherInputStream(new GZIPInputStream(is), cipher);
DataInputStream dis = new DataInputStream(cis);
If you used a writer, obviously you'll need to change the last declaration accordingly:
Reader r = new InputStreamReader(cis);
Of course you need a Key Pair of
PrivateKey PK;
PublicKey Puk;
Those two needs to be saved locally (you need to chose how to, just google it and chose how you want to save them, there're several options).
Now, not knowing how well you know RSA, I'll explain a couple of things:
IMPORTANT before goint to production make sure to have your key pair saved and backupped! Multiple times in different media, if possible. If you lose those keys, your data becomes unreadable, thus lost forever!
Really, protect those keys with evertything you've got!
you use the PublicKey to crypt because this way only those who have the private key can uncrypt it, because, normally, you can distribute the PublicKey, and everybody with the public key can decrypt what was crypted with the PriveteKey. This is used for electronic signatures because only the owner of the PrivateKey can write a document that can be opened with the relative PublicKey. On the opposite, everybody can use the PublicKey to cipher a document but only the one with the associated private key can read it. That's why, if you store protected data, you use the public key to cipher and the private to uncipher. Right now it doesn't matter to you, but better be prepared for the future.
you can use the algorithm you fancy, but the most used is RSA and it's the one you can find the most informations on.
I compress the data before chiphering it not for saving space, but to maximize the randomization of the data, thus making harder to brute-force decipher them. Still, there's a problem: GZip protocol puts GZ before any file compressed with said protocol as signature. You can manually remove that signature before ciphering and add it manually after deciphering, but it become a little more complex to handle. You can bypass the compression part if you want (or find another algorithm to compress/uncompress).

Obfuscating password LDAP AD

I have my parameters in a properties file.
managerDn=cn=read-only-admin,dc=example,dc=com
managerPassword=69BPoqG3sWr/MNspi4ZsDw==
server=ldaps://server.local:636
groupSearchBase=ou=test,dc=example,dc=com
base=dc=example,dc=coms
My password is encrypted, but the client told me: all you have done is encrypt the password and we need it Obfuscating ie making so that no one can read it.
Any idea?
Maybe the best option is to base64 encode the entire property file. It's not encryption but and more "obfuscation". To do this you could do something like this:
//encode:
def encoded = file.text.bytes.encodeBase64().toString()
//decode:
def password = new String(file.text.decodeBase64())
Your property file would like this:
bWFuYWdlckRuPWNuPXJlYWQtb25seS1hZG1pbixkYz1leGFtcGxlLGRjPWNvbQ0KbWFuYWdlclBhc3N3b3JkPTY5QlBvcUczc1dyL01Oc3BpNFpzRHc9PQ0Kc2VydmVyPWxkYXBzOi8vc2VydmVyLmxvY2FsOjYzNg0KZ3JvdXBTZWFyY2hCYXNlPW91PXRlc3QsZGM9ZXhhbXBsZSxkYz1jb20NCmJhc2U9ZGM9ZXhhbXBsZSxkYz1jb21z
here is a link that might help with base64 in Groovy.
NOTE: This really doesn't make anything more secure it's just hiding the plain text. Anyone that knows what they're looking at would decode it the same way you would. It would seem your client isn't familiar with this type of security. There are more secure ways of doing this. You may want to look into salting the actual encryption process or using a token exchange with another service to give you the password.

How can I encrypt password in log4j.properties?

Is there any way that i can encrypt password in log4j.properties
following is my appender
log4j.appender.DB=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DB.URL=jdbc:mysql://localhost:3306/anilpractice
log4j.appender.DB.driver=com.mysql.jdbc.Driver
log4j.appender.DB.user=root
log4j.appender.DB.password=P#ssw0rd
log4j.appender.DB.sql=INSERT INTO logs VALUES('%x','%d{dd MMM yyyy HH:mm:ss}','%C','%p','%m')
log4j.appender.DB.layout=org.apache.log4j.PatternLayout
Please help me out how can i encrypt .password tag?
thank you all.
Thank God, Finally got some solution to keep encrypted password in Log4j.properties
What all we have to do is,
Replicate JDBCAppender class of log4j.jar.
Modify the definition of
public void setPassword(String password)
{
this.databasePassword = password;
}
in JDBCAppender
according to your need And replace that class in log4j.jar.
I don't think that is possible. Even if it's possilbe, consider the following:
If you can establish a connection by only providing an "encrypted password", it's like the password is not encrypted, because everyone who copies the encrypted password can connect and compromise your database. The only different is, that the password is presented in a different way and maybe less human readable, but still fully useful. Even if you implement some symetric unencription of the password in your code, if the attacker has access to your configuration file containing the encrypted password, it is very likely that he has also access to your code running on the same machine containing the unencryption algorithm and would be able to decompile and read the algorithm.
Better create a DB-User with restricted access rights to only write into the logging table. In this way a stolen password can't harm your database very much.

Updating LDAP encrypted password via JNDI

I need some pointers how to update an encrypted password in an LDAP (OpenLDAP) of a user within an LDAP tree. The passwords in the LDAP server are prefixed with {crypt} which I suppose indicates that it is encrypted (with DES?)
I need to write a method which updates a user's passwords. What is the right way to do this? Do I need to prefix the string with {crypt} myself? How do I encrypt the password for {crypt}?
UPDATE:
Just to clarify what I need is the Java code to encrypt the attribute so that it works with {crypt}. I also don't know if I have to prefix the attribute with the string {crypt} myself.
No, you just need to update the attribute, just like any other attribute, but remembering that unlike most attributes it is a byte[] not a String.
There is also an ExtendedOperation for password modification in association with the Password Policy IETF draft, but you haven't mentioned you're using that.
In some cases, using a pre-encoded password might prevent the directory server from enforcing password quality checks.

How to REALLY secure a PDF, using ItextPDF preferably?

I've been working on settting passwords on PDFs to prevent copy/paste and allow printing, add watermarks and set an owner password to prevent further changes.
Everything works well as expected, no issue there.
Then I downloaded this free for 15 days pdf removal tool, a-pdf. In a blink it removes all protection, no matter the complexity of the password (tried with 50 char length will all kind of chars).
I see there are other methods in itextPDF to encrypt a document. I used the following:
File f = new File("C:/TEMP/zip/waterMarked.pdf");
String hardPassword = "D 5BaIZQ# CqAk+NQCW)7Dkgb#i&02ifu!2TMX*d 0TGK(j(Kq";
byte[] hardPasswordByte = hardPassword.getBytes();
PdfReader reader = new PdfReader("C:/TEMP/zip/Original_document-9.pdf");
FileOutputStream out = new FileOutputStream(f);
PdfStamper stamp = new PdfStamper(reader, out);
//first argument is the user password. If set to something it asks for password when opening file, not wanted.
stamp.setEncryption(null, hardPasswordByte, PdfWriter.ALLOW_PRINTING, true);
//do stuff on the stamper, save file.
Does anyone knows a better way to protect PDF documents from Java code ?
PDF files support 2 passwords: user password and owner password. A user can view the PDF file if he knows any of these passwords. If the file has a user password, when the file is opened with a PDF viewer, the viewer asks the user to enter a password and either the user or owner passwords will work. If the file has only an owner password, the document is displayed automatically and the password is required when trying to change the file's access rights. This is the flow of operations suggested by PDF specification, but in reality it works like this: if the file is protected with a user password, brute force approach is required for password cracking, the longer the password is the longer it takes to crack. Problem is your real users need the password to open the file. If the file is protected only with an owner password, there is a default decryption key (remember, any viewer can display the PDF file without requesting a password) and the application that processes the PDF file decides whether to respect or not the document access rights. Once the file has been decrypted, it is saved without encryption and the output file has no longer a password. Since your documents have only the owner password, the tool removes it without problems using the default decryption key.
There are a few solutions (more or less related to iText) depending on your audience:
simple PDF encryption (with the problems above) if your audience is widespread, for example you publish papers on a website; 3rd party DRM solution, more complex and requires various plugins installed on your users' computers; certificate encryption (no sure if iText supports it), again complex, requires each user to have a digital certificate and documents access is defined for each user. Last 2 options work in a controlled enterprise environment.

Categories

Resources