Handling passwords used for auth in source code

45,135

Solution 1


Important note:

If you're designing the authentication system as a whole, you shouldn't store passwords, even if they're encrypted. You store a hash, and check if passwords provided during login match the same hash. That way, a security breach on your database avoids getting your users' passwords exposed.

With that said, for situations where you are going to store data as-is (in this case passwords), then with an inner-to-outer mindset, here are some steps to protect your process:


First step, you should change your password-handling from String to character array.

The reason for this is that a String is an immutable object, and so it's data will not be cleansed immediately even if the object is set to null; The data is set for garbage-collection instead, and this poses security problems because malicious programs might gain access to that String (password) data before it is cleaned.

This is the main reason why Swing's JPasswordField's getText() method is deprecated, and why getPassword() uses character arrays.


The second step is to encrypt your credentials, only decrypting them temporarily during the authentication process. Or to hash them server-side, store that hash, and "forget" the original password.

This, similarly to the first step, makes sure your vulnerability-time is as small as possible.

It is recommended that your credentials are not hard-coded, and that instead, you store them in a centralized, configurable and easily-maintainable manner, such as a configuration or properties file, or a database.

You should encrypt your credentials before saving the file, and additionally, you can apply a second encryption to the file itself (2-layer encryption to the credentials, and 1-layer to other file contents).

Note that each of the two encryption processes mentioned above can be multiple-layered themselves. Each encryption can be an individual application of Triple Data Encryption Standard (AKA TDES and 3DES), as a conceptual example.


After your local environment is properly protected (but remember, it's never ever "safe"!), the third step is apply basic protection to your transmission process, by using TLS (Transport Layer Security) or SSL (Secure Sockets Layer).


The forth step is to apply other protection methods.

For example, applying obfuscation techniques to your "to-use" compile, to avoid (even if shortly) the exposure of your security measures in case your program is obtained by Ms. Eve, Mr. Mallory, or someone else (the bad-guys) and decompiled.


UPDATE 1:

By @Damien.Bell 's request, here is an example that covers the first and second steps:

    //These will be used as the source of the configuration file's stored attributes.
    private static final Map<String, String> COMMON_ATTRIBUTES = new HashMap<String, String>();
    private static final Map<String, char[]> SECURE_ATTRIBUTES = new HashMap<String, char[]>();
    //Ciphering (encryption and decryption) password/key.
    private static final char[] PASSWORD = "Unauthorized_Personel_Is_Unauthorized".toCharArray();
    //Cipher salt.
    private static final byte[] SALT = {
        (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,
        (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,};
    //Desktop dir:
    private static final File DESKTOP = new File(System.getProperty("user.home") + "/Desktop");
    //File names:
    private static final String NO_ENCRYPTION = "no_layers.txt";
    private static final String SINGLE_LAYER = "single_layer.txt";
    private static final String DOUBLE_LAYER = "double_layer.txt";

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws GeneralSecurityException, FileNotFoundException, IOException {
        //Set common attributes.
        COMMON_ATTRIBUTES.put("Gender", "Male");
        COMMON_ATTRIBUTES.put("Age", "21");
        COMMON_ATTRIBUTES.put("Name", "Hypot Hetical");
        COMMON_ATTRIBUTES.put("Nickname", "HH");

        /*
         * Set secure attributes.
         * NOTE: Ignore the use of Strings here, it's being used for convenience only.
         * In real implementations, JPasswordField.getPassword() would send the arrays directly.
         */
        SECURE_ATTRIBUTES.put("Username", "Hypothetical".toCharArray());
        SECURE_ATTRIBUTES.put("Password", "LetMePass_Word".toCharArray());

        /*
         * For demosntration purposes, I make the three encryption layer-levels I mention.
         * To leave no doubt the code works, I use real file IO.
         */
        //File without encryption.
        create_EncryptedFile(NO_ENCRYPTION, COMMON_ATTRIBUTES, SECURE_ATTRIBUTES, 0);
        //File with encryption to secure attributes only.
        create_EncryptedFile(SINGLE_LAYER, COMMON_ATTRIBUTES, SECURE_ATTRIBUTES, 1);
        //File completely encrypted, including re-encryption of secure attributes.
        create_EncryptedFile(DOUBLE_LAYER, COMMON_ATTRIBUTES, SECURE_ATTRIBUTES, 2);

        /*
         * Show contents of all three encryption levels, from file.
         */
        System.out.println("NO ENCRYPTION: \n" + readFile_NoDecryption(NO_ENCRYPTION) + "\n\n\n");
        System.out.println("SINGLE LAYER ENCRYPTION: \n" + readFile_NoDecryption(SINGLE_LAYER) + "\n\n\n");
        System.out.println("DOUBLE LAYER ENCRYPTION: \n" + readFile_NoDecryption(DOUBLE_LAYER) + "\n\n\n");

        /*
         * Decryption is demonstrated with the Double-Layer encryption file.
         */
        //Descrypt first layer. (file content) (REMEMBER: Layers are in reverse order from writing).
        String decryptedContent = readFile_ApplyDecryption(DOUBLE_LAYER);
        System.out.println("READ: [first layer decrypted]\n" + decryptedContent + "\n\n\n");
        //Decrypt second layer (secure data).
        for (String line : decryptedContent.split("\n")) {
            String[] pair = line.split(": ", 2);
            if (pair[0].equalsIgnoreCase("Username") || pair[0].equalsIgnoreCase("Password")) {
                System.out.println("Decrypted: " + pair[0] + ": " + decrypt(pair[1]));
            }
        }
    }

    private static String encrypt(byte[] property) throws GeneralSecurityException {
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(PASSWORD));
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
        pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(SALT, 20));

        //Encrypt and save to temporary storage.
        String encrypted = Base64.encodeBytes(pbeCipher.doFinal(property));

        //Cleanup data-sources - Leave no traces behind.
        for (int i = 0; i < property.length; i++) {
            property[i] = 0;
        }
        property = null;
        System.gc();

        //Return encryption result.
        return encrypted;
    }

    private static String encrypt(char[] property) throws GeneralSecurityException {
        //Prepare and encrypt.
        byte[] bytes = new byte[property.length];
        for (int i = 0; i < property.length; i++) {
            bytes[i] = (byte) property[i];
        }
        String encrypted = encrypt(bytes);

        /*
         * Cleanup property here. (child data-source 'bytes' is cleaned inside 'encrypt(byte[])').
         * It's not being done because the sources are being used multiple times for the different layer samples.
         */
//      for (int i = 0; i < property.length; i++) { //cleanup allocated data.
//          property[i] = 0;
//      }
//      property = null; //de-allocate data (set for GC).
//      System.gc(); //Attempt triggering garbage-collection.

        return encrypted;
    }

    private static String encrypt(String property) throws GeneralSecurityException {
        String encrypted = encrypt(property.getBytes());
        /*
         * Strings can't really have their allocated data cleaned before CG,
         * that's why secure data should be handled with char[] or byte[].
         * Still, don't forget to set for GC, even for data of sesser importancy;
         * You are making everything safer still, and freeing up memory as bonus.
         */
        property = null;
        return encrypted;
    }

    private static String decrypt(String property) throws GeneralSecurityException, IOException {
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(PASSWORD));
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
        pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
        return new String(pbeCipher.doFinal(Base64.decode(property)));
    }

    private static void create_EncryptedFile(
                    String fileName,
                    Map<String, String> commonAttributes,
                    Map<String, char[]> secureAttributes,
                    int layers)
                    throws GeneralSecurityException, FileNotFoundException, IOException {
        StringBuilder sb = new StringBuilder();
        for (String k : commonAttributes.keySet()) {
            sb.append(k).append(": ").append(commonAttributes.get(k)).append(System.lineSeparator());
        }
        //First encryption layer. Encrypts secure attribute values only.
        for (String k : secureAttributes.keySet()) {
            String encryptedValue;
            if (layers >= 1) {
                encryptedValue = encrypt(secureAttributes.get(k));
            } else {
                encryptedValue = new String(secureAttributes.get(k));
            }
            sb.append(k).append(": ").append(encryptedValue).append(System.lineSeparator());
        }

        //Prepare file and file-writing process.
        File f = new File(DESKTOP, fileName);
        if (!f.getParentFile().exists()) {
            f.getParentFile().mkdirs();
        } else if (f.exists()) {
            f.delete();
        }
        BufferedWriter bw = new BufferedWriter(new FileWriter(f));
        //Second encryption layer. Encrypts whole file content including previously encrypted stuff.
        if (layers >= 2) {
            bw.append(encrypt(sb.toString().trim()));
        } else {
            bw.append(sb.toString().trim());
        }
        bw.flush();
        bw.close();
    }

    private static String readFile_NoDecryption(String fileName) throws FileNotFoundException, IOException, GeneralSecurityException {
        File f = new File(DESKTOP, fileName);
        BufferedReader br = new BufferedReader(new FileReader(f));
        StringBuilder sb = new StringBuilder();
        while (br.ready()) {
            sb.append(br.readLine()).append(System.lineSeparator());
        }
        return sb.toString();
    }

    private static String readFile_ApplyDecryption(String fileName) throws FileNotFoundException, IOException, GeneralSecurityException {
        File f = new File(DESKTOP, fileName);
        BufferedReader br = new BufferedReader(new FileReader(f));
        StringBuilder sb = new StringBuilder();
        while (br.ready()) {
            sb.append(br.readLine()).append(System.lineSeparator());
        }
        return decrypt(sb.toString());
    }

A full example, addressing every protection step, would far exceed what I think is reasonable for this question, since it's about "what are the steps", not "how to apply them".

It would far over-size my answer (at last the sampling), while other questions here on S.O. are already directed on the "How to" of those steps, being far more appropriate, and offering far better explanation and sampling on the implementation of each individual step.

Solution 2

If you are using basic auth, you should couple that with SSL to avoid passing your credentials in base64 encoded plain text. You don't want to make it easy for someone sniffing your packets to get your credentials. Also, don't hard code your credentials in your source code. Make them configurable. read them from a config file. You should encrypt the credentials before storing them in a config file and your app should decrypt the credentials once it reads them from the config file.

Solution 3

It's generally not good advice to encrypt credentials. Something that is encrypted can be decrypted. Common best practice is to store passwords as a salted hash.A hash cannot be decrypted. The salt is added to defeat brute force guessing with Rainbow Tables. As long as every userId has its own random salt, an attacker would have to generate a set of tables for every possible value of the salt, quickly making this attack impossible within the lifespan of the universe. This is the reason why websites generally can't send you your password if you have forgotten it, but they can only 'reset' it. They don't have your password stored, only a hash of it.

Password hashing is not very difficult to implement yourself, but it's such a common problem to solve that countless others have done it for you. I've found jBcrypt easy to use.

As an extra protection against brute force guessing of passwords, it is common best practice to force a userId or remote IP to wait a few seconds after a certain number of login attempts with the wrong password. Without this, a brute force attacker can guess as many passwords per second as your server can handle. There is a huge difference between being able to guess 100 passwords per 10 second period or a million.

I get the impression that you have included the username/password combination in your source code. This means that if you ever want to change the password, you'll have to recompile, stop and restart your service, and it also means that anyone who gets a hold of your source code, also has your passwords. Common best practice is never to do this, but to store the credentials (username, password hash, password salt) in your datastore

Solution 4

Why not store credentials in source code

It is generally a good idea to avoid to store credentials in source code. The issue is, that access to code and who should have access to the credentials often changes over time. Once a project becomes more mature there are usually some developers who do not need to know and hence should not know certain credentials. In addition code may be reused for slightly different purposes or even become open source. Also, as the code base grows more complex, it becomes very tedious to identify credentials being buried somewhere in the middle of the code.

It seems safe to say that hundreds of millions of users have already been affected by issues caused by hard-coded credentials. Here is an article with some examples.

How to provide credentials to your app

If credentials are not part of the code, this raises the question how you can provide credentials to your application. This depends on the platform on which your application runs. For instance if you host your application on some cloud service, this service will have a mechanism to store credentials in a save way and inject them into the operation system environment of your application. To provide a specific example, here is the documentation how to provide credentials for an app hosted on Heroku. In you application code you can then access them from the environment. E.g. for Java you could use getenv

String apiPassword = getenv("API_PASSWORD");

Here API_PASSWORD needs to be provided in the environment by the hosting mechanism of your app.

Further Reading

I have written a blog article about the topic that covers this topic in more detail: Keep passwords out of source code - why and how.

Solution 5

  1. secure computer that initializes the request (your computer). if that machine is insecure, nothing will protect you. that's completely separate topic (up-to-date software, properly configured, strong passwords, encrypted swap, hardware sniffers, physical security etc)
  2. secure your storage the medium you use for storing your credentials should be encrypted. decrypted credentials should be stored only in ram of your secured machine
  3. people that maintain that hardware must be trusted (probably the weakest link)
  4. they also should know as few as possible. that's a protection from rubber-hose cryptanalysis
  5. your credentials should fulfil all the security recommendation (proper length, randomness, single purpose etc)
  6. your connection to remote service must be secured (SSL etc)
  7. your remote service must be trusted (see points 1-4). plus it should be hacking prone (if your data/service is insecure then securing your credentials is pointless). plus it should not store your credentials

plus probably thousand things i forgot about :)

Share:
45,135
A_Elric
Author by

A_Elric

Updated on July 08, 2022

Comments

  • A_Elric
    A_Elric almost 2 years

    Assuming that I'm trying to pull from a RESTful api that uses basic authentication / basic certificates, what would be the best way to store that user name and password in my program? Right now it's just sitting there in plaintext.

    UsernamePasswordCredentials creds = new UsernamePasswordCredentials("myName@myserver","myPassword1234");
    

    Is there some way of doing this that is more security minded?

    Thanks

  • A_Elric
    A_Elric over 11 years
    Can you provide some examples on how you would do this programmatically?
  • Athens Holloway
    Athens Holloway over 11 years
  • Athens Holloway
    Athens Holloway over 11 years
    Nice response. There is definitely a common theme here. +1 for the char[] recommendation.
  • A_Elric
    A_Elric over 11 years
    I love this answer, but at the risk of it becoming too verbose, I'd love to see an example of each step's source code implemented.
  • CosmicGiant
    CosmicGiant over 11 years
    [*] - @Damien.Bell For the sake of not leaving your request unattended, I've included an example that covers the first (~) and second steps. --- As for why not all steps, well, as you can see, it is not something you can sample with a tiny little snippet of code; And an example for network protection would require even more than that of the local scope, even if to be partially pseudo-coded. Obfuscation, also, has a very wide range of methods of implementation, and although it's simple in concept, the fact it is applied to the source-code itself means it's hard to explain in samples.
  • Jarrod Smith
    Jarrod Smith over 11 years
    Finally, run an obfuscation tool like ProGuard on your source. Java byte code is notoriously easy to disassemble and analyse. Obfuscation is the icing on your security cake, and makes it much more difficult for someone to reverse engineer your code and potentially hack your security measures. See: proguard.sourceforge.net/index.html#manual/introduction.html
  • CosmicGiant
    CosmicGiant over 11 years
    @JarrodSmith - That is exactly what I mean with the obfuscation part. +1 for the nice way of explanation and for pointing to a good tool.
  • Woot4Moo
    Woot4Moo over 11 years
    Agree with everything except the encrypting of credentials. You would generate a hash and compare the two, not encrypt them.
  • CosmicGiant
    CosmicGiant over 11 years
    @Woot4Moo - By what I understand, since he is trying to pull from a non-local entity (server), the scope is not that of the authentication process from the authenticator's (server's) perspective, but from the client's. --- As such, the client must protect the credentials in storage and transmission, but send the credentials as they are. Transmission security is handled by the 3rd step, which has encryption, hashing and message-digesting inherently. ___ The server is where such hash-comparison is applicable, and the client shouldn't do server-duty processes, for security reasons.
  • CosmicGiant
    CosmicGiant over 11 years
    I am still unsure, but I think "... I'm trying to pull from a RESTful api ..." indicates the OP is not talking about the server-side environment. It is my belief he is talking about a client-side application that authenticates with a server. __ As such, the client-side should only protect the credentials in-storage (encryption) and securely send them to the server (TSL / SSL - Which inherently apply encryption and message-digesting) ___ The message-digest (for register or comparison) should be done server-side only, as otherwise it would be insecure. ___ It's all on my answer's comments.
  • CosmicGiant
    CosmicGiant over 11 years
    Also, your answer is indicating the use of an possibly outdated API (jBcrypt - It's on beta v0.3, and last updated in January 2010, which is a possible indication that the project has died out). Java already has it's own standard message-digesting classes, and I don't think there is any essential need for 3rd party APIs.
  • CosmicGiant
    CosmicGiant over 11 years
    "If you cannot trust the environment your program is running in, ..., there is nothing you can do to secure your credentials." - If that was true, pretty much every application that has an "auto-fill" option for the credentials would be in very deep trouble. ___ Many two-ended applications (this question's?) like multiplayer games and web-based applications store the account credentials locally, and they rarely have any serious security trouble. ___ Data is never ever 100% safe, regardless of environment. A trusted environment is just another security ("safer") step.
  • Twilite
    Twilite over 11 years
    Well, in the given scenario, you can obfuscate your credentials, but not reach 100% (cryptographic) security. The most you can hope for is to make it so complicated for the attacker to get the clear text passwords, that it is not worth their effort. All it takes to get the stored passwords of a typical web based application, is to go to your browser's options menu and select "show passwords".
  • CosmicGiant
    CosmicGiant over 11 years
    You can never reach 100% security, be it in this or in any other scenario. This is because in the end, it all comes down to sequences of 0 and 1 in memory, which is achieved following an specific set of logical rules, which inherently is always somehow reversible. ___ The basis of cryptographic security is, always was, and will probably always be, "to make it so difficult it isn't worth the effort." ___ Lastly, you are mistaking browser's auto-fill/login (which is for websites), with application's auto-auth/login (which is saved to encrypted files and there only).
  • Twilite
    Twilite over 11 years
    You should read up on cryptography. There are various methods to irreversibly encrypt data, just have a look at "one way hashes" (md5) or public key cryptography, where it's not possible to decrypt encrypted data, even if you have both the encrypted data and the encryption key. With these methods you gain factual 100% security.
  • CosmicGiant
    CosmicGiant over 11 years
    Actually, no. - Like I said, the methods follow an specific set of logical rules, and those have a way to reverse. ___ In the case of cryptographic hash functions, if the hacker knows the set of rules that generated the hash, he can RE a few bits of the original data and get a fair general idea of what the original's length might be. --- It's a lot of brute-forcing and guesswork, but it's not 100% unbreakable. And it's far from the infinite number of attempts of 100% security ___ I don't think any hacker would bother trying tough; It's way far from worth the effort, no matter the reward.
  • CosmicGiant
    CosmicGiant over 11 years
    In fact, theoretically, even protection that would need "infinite number of attempts to break" is not 100% safe; As it itself suggests, all that is needed is the execution of an infinite number of attempts to break it, and eventually, one of the attempts will hit the jackpot.
  • Twilite
    Twilite over 11 years
    Well that's why I wrote "factual 100%". The common example is for a successful attack to likely take longer than the existence of the universe. It's a bit like coming up with the exact wording of any given novel on the first try just by guessing.
  • Mzzl
    Mzzl over 11 years
    It looks like you're right about the client vs server side confusion. I'd still recommend putting the credentials in a data store, not in the source code, but you're right about needing encryption rather than hashing in that case.
  • Mzzl
    Mzzl over 11 years
    Bcrypt is not a message digest, but a blowfish based key generation scheme. I use it as part of SpringSecurity, which is very much alive. Plain message digest algorithms such as SHA-1 or MD5, are not intended for password hashing, but for fast hashing. If you need to hash a chunk of video or text as fast as possible, you can use these, or their more modern replacements. If you're interested in hashing passwords, speed is your enemy. The faster the hashing algorithm used, the faster a brute force attack can succeed.
  • CosmicGiant
    CosmicGiant over 11 years
    @ "longer than the existence of the universe" - For the narrowed possibilities of the example I used, I think a serious hacker with a few zombie-machines wouldn't take more than a few months or a couple of years at best. ___ With something as ridiculously slow as a 100 ms/attempt, a single machine can make over 315 million attempts in one year; Try that with 100 machines and your best protection is probably waving you bye-bye. ___ But if you ain't satisfied with that: One of the smallest bot-nets dismantled so far had 10,000 zombies, and the current record-holder had over 30 million zombies.
  • CosmicGiant
    CosmicGiant over 11 years
    You don't see such things because: 1-A hacker would never receive money worth the process, as the contractors for such jobs have more direct approaches (*cough* buying someone's lips *cough*) to obtain the data; Far faster and cheaper. ___ 2-Such bot-nets already give good profit to the hackers, and buying out he/she's bot-net's processing power is not easy; No contractor would be smart in paying X millions to a hacker when he can *cough* do something else *cough* for X thousands. ___ Extra-long-story-short, it's never worth it for either parties, and it just doesn't happen.
  • Twilite
    Twilite over 11 years
    Please read this article on wikipedia on strong cryptography: en.wikipedia.org/wiki/Strong_cryptography
  • Twilite
    Twilite over 11 years
    Sorry, the article is actually rather vague and more or less arguing your point. What I've been trying to explain all the time, is that there are cryptographic methods that derive their security from their exponential growth in complexity, which makes them prone to brute force attacks for the foreseeable future.
  • CosmicGiant
    CosmicGiant over 11 years
    Hmm. Some google-searching suggests me Blowfish is an encryption (decryptable) while jBcrypt's page indicates it uses a blowfish-based message-diggest (a cryptographic hash function) ... I'm confused. ___ SpringSecurity is alive, Bcrypt might not be; they are separate projects. ___ Anyway, Java 1.7 already incorporates the blowfish cipher, and the modular structure of the Security class allows for it's easy-enough implementation as a security.Provider even in older versions, so I still don't see the need for 3rd-party APIs.
  • Mzzl
    Mzzl over 11 years
    Password hashing is not just about a cypher or a message digest. The aim of schemes like Bcrypt is to make brute forcing a hash computationally expensive. In this case, by running the digest function a certain number of times (default 2**10). Underneath, these schemes use a standard or a customized message digest algoritm.
  • CosmicGiant
    CosmicGiant over 11 years
    I didn't say cryptographic hash functions were just about cyphers or MD, quite the opposite: I said I don't understand how or why would Bcrypt base it's MD algorithm based on an algorithm that has a different (encryption) purpose. ___ If with "running the digest function a certain number of times" you mean to repeat the hashing in a layering manner as is done with encryption, that's usually (if not done right) a bad thing to do. Unless done very properly and precisely, rather than increasing security, you are increasing collision risks, and probably decreasing security.
  • CosmicGiant
    CosmicGiant over 11 years
    Your answer covers both client' and server-side protection steps in a summarized, yet very clear and "followable" way. I liked it very much! [+1] --- There are a few things I think should be explained just a tiny little further, and since there were a few spelling and formatting issues present too, I took the liberty to edit. --- The general structure, as well as most of the text, is unchanged. I just added what I thought was lacking, and reorganized the existing text to fit with it. I hope you don't mind.
  • piotrek
    piotrek over 11 years
    i don't mind spelling, links, grammar, etc. thank you for that. however, if you want to add something plz don't change my answer. if you feel something is missing add a comment or create your own answer. i prefer to sign only under my own words
  • CosmicGiant
    CosmicGiant over 11 years
    I understand. --- Well, my edit didn't really change your answer's meaning in any way. Most of it was fixing spelling and format, and the formatting that needs fixing requires slight text changes anyways. The few additional explanations were just extensions of what was already being said. --- In any case, please fix the spelling (uppercase at phrase-starts is the main problem) and format (separate "topic" from "content" correctly), applying the necessary to-fit adjustments to the text. Also, see #7's "prone". --- And, of course, taking the additional into account when doing it would be nice.
  • Brian McCutchon
    Brian McCutchon over 7 years
    Re: obfuscation, what about open-source software? It seems like obfuscation is useless if your source is on GitHub.
  • CosmicGiant
    CosmicGiant over 7 years
    @BrianMcCutchon A few options off top my head: 1->Ugly) You can release "open-source" with obfuscation applied to the source (but that goes against at least the spirit of open-source licences, and is (far) less effective than obfuscation tools to compiling code. 2->Bad?) You can simply refrain from releasing the security classes publicly, while the rest of the software remains open-source. 3->No idea) You can have security measures that are (automagically) tailored to be per-user (on install?), which self-compile + self-obfuscate (server/using reflection?), based on secure user-specific stuff.
  • CosmicGiant
    CosmicGiant over 7 years
    @BrianMcCutchon No idea if or how much those ideas are good, other than what should be apparent to any programmer dealing with data-security. But sincerely, "just don't do open-source on stuff that needs security" would be my advice. I never did it, and I don't think I ever will; out of my own experience, I don't see a single good argument for it. But if someone knows better, this is interesting, and I would be grateful to be enlightened... One last thing: If your Q is related to having a free version-control host that allows private repositories, I use bitbucket for closed-source projects.
  • Roland
    Roland over 7 years
    Is CharBuffer ok?
  • CosmicGiant
    CosmicGiant over 7 years
    @Roland I haven't programmed anything in Java for the last year or so, so I don't remember about CharBuffer specifically off the top of my head, but basically, if it's not immutable (can get it's internal data overwritten to null or zeroes without waiting for GC), then you can use it, as long as you don't forget to clean it up.
  • Herr Derb
    Herr Derb almost 6 years
    Having all the decryption and encryption information (including salt) in my source code, how is this safer?
  • CosmicGiant
    CosmicGiant almost 6 years
    Did you read all of the answer, rather than just the example code?
  • CosmicGiant
    CosmicGiant over 3 years
    OP had a situation of storing credentials, but that was not the question. The OP was specifically asking about security. => "Is there some way of doing this that is more security minded?"
  • Cybermonk
    Cybermonk over 3 years
    I don't understand what you mean by that comment. OP came here with a situation in mind, you can't take a statement out of context if that's what you're referring to. Nonetheless I've provided simple but effective way to secure access to password within JVM and while transmitting. I can help clarify with details but I don't think that's needed as the question is about the approach and not implementation. Also No matter how security conscious you're, you can't hash and store a password that you wish to use to access a 3rd party site.
  • CosmicGiant
    CosmicGiant about 3 years
    I'm not taking anything out of context. The issue is you don't seem to understand the OP, or this site in general: He made you a specific question. You should give him an answer pertaining to that question. --- Also. Storing passwords as a class in the app, you are literally puting your password in source-code. That's one of the worst solutions possible for storing paswords. And if you're not talking about that, then you need a file, which means plaintext < binary < encrypted. --- Your "answer" outright ignores security; it's equivalent to "to store passwords, just store passwords!".
  • Falk Tandetzky
    Falk Tandetzky almost 3 years
    @HerrDerb your question is exactly to the point. This answer covers how to handle passwords that are entered by a user. What it does not answer is how to handle a scenario in which the application needs credentials that are not provided by a user. I added an answer to cover that topic. This is also covered here: medium.com/twodigits/…