0

At some part of the code that I've been working on I am tempted to use the constructor in an unusual way. The goal is to have minimal to none sensitive values inside string pool.

public class MyClass{
    private String mySafeString;

    public MyClass(char[] aCharArray, String salt) {
         this.mySafeString = Encrypt.encrypt(new String(aCharArray), salt);
    }
    
    public String getMySafeString(){
         return this.mySafeString;
    }
}

...
public static void main(String[] args){
    String salt = getSaltFromSomewhere();
    char[] someKey = new char[]{'c', 'x'};
    var myObject = new MyClass(someKey, salt);
    var encryptedSafeString = myObject.getMySafeString();
}

By creating the String object like that I am avoiding the value's presence inside the string pool. Thereby, intending to leave it to GC to perish the object.

However, I fail to find any resource that forbids the usage of constructor like the way I used it. I am keen to know if it is a bad practice in any way?

Could you please be so kind and advise me on my approach?

Shayan Ahmad
  • 952
  • 8
  • 17
  • 1
    What do you mean by "sensitive values"? Are you talking about passwords and the like? – Louis Wasserman Feb 14 '22 at 01:41
  • Yes, some thing of that nature. Not exactly passwords. – Shayan Ahmad Feb 14 '22 at 01:42
  • Does this answer your question? [Java storing sensitive 'key' as String or char\[\]?](https://stackoverflow.com/questions/12013438/java-storing-sensitive-key-as-string-or-char) – andreoss Feb 14 '22 at 01:43
  • Where did that **char[]** come from? Some **String** the caller had? – passer-by Feb 14 '22 at 01:44
  • Not really @andreoss, I am already using chars and then rewriting the memory with `0`s. The constructor will be encrypting values. Let me update my example to make it more clear. – Shayan Ahmad Feb 14 '22 at 01:45
  • @passer-by, it's a contrived example. I am taking a very small piece of quite some large piece of logic. I want the creation of the object where the salt value encrypts the object right away. – Shayan Ahmad Feb 14 '22 at 01:50
  • I don't understand the question. You are using one of the documented public constructors of String. So what's the issue? – President James K. Polk Feb 14 '22 at 01:51
  • @PresidentJamesK.Polk, could you please notice the constructor of `MyClass`? Also the instance members. – Shayan Ahmad Feb 14 '22 at 01:52
  • Is it a bad practice? – Shayan Ahmad Feb 14 '22 at 01:54
  • 2
    No, it's not bad practice. Java is not in my experience a language with lots of secret gotchas. Looks at the Javadocs, pick the methods that are most suitable, declare victory. – President James K. Polk Feb 14 '22 at 01:56
  • 1
    Taking a `char[]` and converting it to `String` in a constructor is not a bad practice in and of itself. But inventing your own solutions to security problems is **definitely** a bad practice! The best practice here is to find an existing third-party library with a good reputation which does what you want. Also be aware that because [`sun.misc.Unsafe`](http://mishadoff.com/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/) exists, keeping sensitive data out of the string pool is not enough to stop malicious code from inside the same JVM from accessing it, not to mention code *outside* the JVM. – kaya3 Feb 14 '22 at 02:22

3 Answers3

3

That's a standard way to convert a char[] to a String.

You might also want to see if your encryption library can work from a char[] or InputStream, so that you can avoid creating any String.

Chris Foley
  • 454
  • 3
  • 5
1

The goal is to have minimal to none sensitive values inside string pool.

That's a non-goal. Strings only get placed in the string pool if they are either compile time constants OR if some code explicitly calls String.intern to put them in the string pool.

Your real goal is to avoid leaving sensitive information somewhere in memory ... or in a swap file ... where a bad guy may be able to retrieve it.


However, I fail to find any resource that forbids the usage of constructor like the way I used it. I am keen to know if it is a bad practice in any way?

I doubt that you will find anything that forbids this1.

However, it is not clear from the code what it achieves and how you intend to use it.

Is it your intention that the "safe" string be decryptable or not?

  • If Yes, you have a big problem. In order to decrypt, you need the decryption key in memory at some time. If the cipher algorithm is symmetric, that means that salt is the decryption key. But you have already put that onto the heap as a String object. (Ooops!)

    And if you avoid that oops, the next problem is that the bad guy will be able to reverse engineer getSaltFromSomewhere() or the equivalent that generates the decryption key in the case of an asymmetric cipher. They may then be able to recover the key. Note that in order to successfully decrypt, your application must be able to obtain the correct key ... in memory ... to do the decryption.

  • If No, then it strikes me that the "safe" string could actually be replaced with a cryptographic hash of the original string. You don't necessarily need a salt for that. And if you do need one, you don't need the seed to be generated securely.

Also, it is not sufficient to just use a char[] to avoid storing the unencrypted (etc) secret in a String. The char[] is also in the heap. So it is also imperative that you overwrite the char[] when you are finished with it. A secret in a char[] or byte[] or Buffer, etc can be found just as easily as a secret in a String.

Finally, you probably should be doing a thorough risk assessment to decide whether the effort of protecting strings in the heap is actually going to be worth it. What is the chance that the bad guys can get in to capture a heap dump? If they can get in that way, can they intercept the secrets some other way; e.g. by surreptitiously replacing some of your Java app code, attaching a debugger, stealing keys out of config files, etc.

1 - Normal Java coding standards don't concern themselves with protecting secrets, and security standards don't concern themselves with Java style, etc issues.


In short, there is nothing wrong with the constructor per se, but the chances are that it doesn't solve the real problem.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
0

I think you mean safe means that the string won't be modified outside of the class. As a result, you are making a copy.

You don't need to do this for String because strings are immutable. There's no way to modify the string outside of the class even if there's a reference to the string outside of the class.

Cheng Thao
  • 1,467
  • 1
  • 3
  • 9
  • Hi Cheng, thank you for your answer. But that is not what I am looking for. Sorry that I literally just updated the example. I am aware about the immutability of the String. That has very little to do with what I am trying to achieve here, Sir – Shayan Ahmad Feb 14 '22 at 01:51