Encrypt passwords as securely as possible

1

I'd like to know how to encrypt passwords on Android and what are the best practices.

I'm using Eclipse, SQlite database to store the password locally and MySql with PHP to store on the server via HttpClient . My application will be of use online and offline. Therefore any registration or change of user data is done on the server and only later locally, that is, online only that the user can register or change their data.

One good alternative would be to encrypt the password, generate a hash to prevent it from being changed during the send to server, and generate a sort of device signing hash so the server knows that the password came from a device with the installed application and concatenate everything would look like this:

"Encrypted Password" + "Integrity Hash" + "Authash Hash"

And the server would check all of this and store it all together locally and externally.

    
asked by anonymous 08.01.2016 / 18:18

2 answers

2
  One good alternative would be to encrypt the password, generate a hash to prevent it from being changed during the send to server, and generate a sort of device signing hash so the server knows that the password came from a device with the installed application and concatenate everything would look like this:

Never invent your own encryption! The chances of something going wrong are enormous. Instead, use a well-established protocol for whatever:

  • Connect to your server using SSL / TLS. So the data you send to it will already be confidential and up-to-date, there is no need to either encrypt the password or generate a hash (in fact, a hash does not prevent it from being changed during sending, a MAC maybe, but that's another story) . And if you combine this with a client authentication using certificates, you already guarantee authenticity as well, just send the same simple password and that's it!

  • If you need to store the user's password on the device (it's not clear in the question whether the user will have to enter it every time they connect to their server, or if that will be saved on the device) some feature of the system itself to assist you. I have no experience with Android, but a quick search brought me the AccountManager - I think be a centralized means of managing the accounts that the user has in various services. I suggest taking a look at it.

  • Detailing

    If what I have explained above is not clear, let me break the problem into smaller parts to make it easier to understand the proposed solution (and perhaps to come up with some alternatives):

    Saving passwords on the device

    Unless you want the user to enter your password each time you connect to your server, some authentication method needs to be stored on the device. In that case, you can not do a hash of the password because you need the password in its original format to send to the server (otherwise the hash password ), and any attacker who obtains a copy of the hash has the necessary credentials to authenticate with the server). Encrypting is an idea, but where to store the key? This is a complicated situation, hence my suggestion to use what you already have on Android and get it out of your head ...

    Communicating securely with the server

    If you do not use SSL / TLS (eg HTTPS), you can not guarantee that communication with the server will not be intercepted and even modified (particularly in open networks). Trying to "flip" without TLS will leave you with an insecure solution and / or it will force you to reinvent many wheels. So I strongly suggest using this protocol.

    When creating a secure channel via TLS, you can send the user's credentials in a flat format, without the need to encrypt. Because the protocol guarantees both the confidentiality (i.e. nobody can read the communication) and the integrity (no one can change the communication) of both, as well as the authenticity of the server (the client knows that it is communicating with the right server).

    Authenticating the device

    In the question you are concerned about the device that originated the request ("... for the server to know that the password came from a device with the application installed ..."). That is, in addition to authenticating the user with the server, you also want to authenticate the device with the server.

    At first, this can also be done via SSL / TLS, with the use of client certificates. Roughly, when installing the application it would generate a certificate for that device, register that certificate on the server (or simply have that certificate signed by an CA that the server trusts), and then communicate with TLS using that certificate with the protocol. So both client and server would be authenticated to each other, and you would then simply authenticate the user (sending the password in its normal format).

    If all this is very complicated, a simpler alternative would be to generate a random password to be the "device password", and register it on the server next to the user's password. This password would then be sent during authentication, also under the previously established secure channel.

    Saving passwords on the server

    On the server, of course, you will not save the password (s) in flat format, but rather a hash of the same one (s). See the question "Hashing passwords from safe way? " for more details.

        
    14.01.2016 / 22:21
    0

    After some research I found an example ready using AES in this site: link

    It worked well it encrypts and decrypts too, for me I only wanted one that only encrypted without being able to decrypt, but this one serves for now. My question in this code is regarding this encryption method I do not know if it will generate some encrypted code with this "#" character, since I am using it and this "^" to separate the string and mount the fields to store in the Bank. The method is this:

    public static String encrypt(String plainText, String password)    throws
      NoSuchAlgorithmException,
      InvalidKeySpecException,
      NoSuchPaddingException,
      InvalidParameterSpecException,
      IllegalBlockSizeException,
      BadPaddingException,
      UnsupportedEncodingException,
      InvalidKeyException,
      InvalidAlgorithmParameterException
    {
      byte[] saltBytes = salt.getBytes("UTF-8");
      byte[] ivBytes = initializationVector.getBytes("UTF-8");
      SecretKeyFactory factory =   SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    
      PBEKeySpec spec = new PBEKeySpec(
           password.toCharArray(),
           saltBytes,
           pswdIterations,
           keySize
      );
      SecretKey secretKey = factory.generateSecret(spec);
      SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
      cipher.init(Cipher.ENCRYPT_MODE, secret, new       IvParameterSpec(ivBytes));
      byte[] encryptedTextBytes =  cipher.doFinal(plainText.getBytes("UTF-8"));
      return Base64.encodeToString(encryptedTextBytes, 0);
    }
    

    And if anyone has a better suggestion, it would be a great help.

        
    10.01.2016 / 04:37