-1

im looking for a way to encrypt a four digits password and as a result get a 16chars string.

So far ive got 64chars String using this

public static String digestHex(String text) {
    StringBuilder stringBuffer = new StringBuilder();
    try {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");// SHA-256
        digest.reset();
        for (byte b : digest.digest(text.getBytes("UTF-8"))) {
            stringBuffer.append(Integer.toHexString((int) (b & 0xff)));
        }
    } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return stringBuffer.toString();
}

being text = 1234 the resulting String is = 3ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4 Using Java btw :D

dbncourt
  • 560
  • 4
  • 10
  • 27
  • Don't do this. If you use only 16 characters, it will be too easy to decrypt, and unsafe. – Ryan Shillington Apr 29 '14 at 15:25
  • md5 is 16 bytes (but usually 32 hex chars representation) (that's as small as they come) – njzk2 Apr 29 '14 at 15:29
  • You are saying "encrypt" when really you mean "hash". You may want to change your wording before the "OMG DON'T ENCRYPT YOUR PASSWORDS" folks turn up and don't read your question carefully enough :-) – Duncan Jones Apr 29 '14 at 15:35
  • Where does this restriction come from, the 16 characters i mean? Does such an implementation already exists, do you have access to the source code, is someone demanding this from you? In any case, this scheme with 4 digit passwords can never ever be safe. – martinstoeckli Apr 29 '14 at 19:43

3 Answers3

1

Any "encryption" scheme where you are encrypting a 4 digit number without an additional key is effectively a lookup scheme. Since there are only 10,000 unique "inputs" to the lookup scheme, it will be relatively easy to crack your encryption ... by trying all of the inputs.

In other words, the security of your encrypted PIN numbers is an illusion ... unless you do something like "seeding" the input before you encrypt it.

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

You are using SHA-256. This algorithm generates 32 bytes long messages (256 bits, more details here).

This is why you obtain a 64 bytes long hex string as an output: Integer.toHexString((int) (b & 0xff)) converts each single b byte of the MessageDigest into a 2 bytes long hex String representation.

To obtain a 16 bytes long String, you can either use MD5 (16 bytes output, 32 if converted in hex), derive that string or use a completely different way such as actually using encryption (using javax.crypto.Cipher).

I'd need to know what you would like to to to elaborate further, knowing that using MessageDigestis actually hashing, not encryption, while in the first line of your post you are speaking of encryption. One of the difference resides in the fact that hash codes are not designed to be reversed but compared, unlike encryption which is reversible. See this interesting SO post on this.

Community
  • 1
  • 1
Shlublu
  • 10,917
  • 4
  • 51
  • 70
0

The security of you scheme aside - there are easier ways to do this:

// Your original - with the horrible exception hiding removed.
public static String digestHex(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException {
    StringBuilder stringBuffer = new StringBuilder();
    MessageDigest digest = MessageDigest.getInstance("SHA-256");// SHA-256
    digest.reset();
    for (byte b : digest.digest(text.getBytes("UTF-8"))) {
        stringBuffer.append(Integer.toHexString((int) (b & 0xff)));
    }
    return stringBuffer.toString();
}

// Uses BigInteger.
public static String digest(String text, int base) throws NoSuchAlgorithmException, UnsupportedEncodingException {
    MessageDigest digest = MessageDigest.getInstance("SHA-256");// SHA-256
    digest.reset();
    BigInteger b = new BigInteger(digest.digest(text.getBytes("UTF-8")));
    return b.toString(base);
}

public void test() throws NoSuchAlgorithmException, UnsupportedEncodingException {
    System.out.println("Hex:" + digestHex("1234"));
    System.out.println("Hex:" + digest("1234", 16));
    System.out.println("36:" + digest("1234", 36));
    System.out.println("Max:" + digest("1234", Character.MAX_RADIX));
}

This allows you to generate the string in a higher base - thus shortening the number but sadly you still do not achieve 16.

I would suggest you use one of the simple CRC algorithms if you are really instistent on 16 characters. Alternatively you could try base 62 or base 64 - there are many implementations out there.

OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213