How to encrypt String in Java

What I need is to encrypt string which will show up in 2D barcode(PDF-417) so when someone get an idea to scan it will get nothing readable.

Other requirements:

  • should not be complicated
  • it should not consist of RSA, PKI infrastructure, key pairs, etc.

It must be simple enough to get rid of the people snooping around, and easy to decrypt for other companies interested in getting that data. They call us, we tell them the standard or give them some simple key which can then be used for decryption.

Probably those companies could use different technologies so it would be good to stick to some standard which is not tied to some special platform or technology.

What do you suggest? Is there some Java class doing encrypt() decrypt() without much complication in achieving high security standards?

12 thoughts on “How to encrypt String in Java”

  1. I’d recommend to use some standard symmetric cypher that is widely available like DES, 3DES or AES. While that is not the most secure algorithm, there are loads of implementations and you’d just need to give the key to anyone that is supposed to decrypt the information in the barcode. javax.crypto.Cipher is what you want to work with here.
    Let’s assume the bytes to encrypt are in
    byte[] input;
    Next, you’ll need the key and initialization vector bytes
    byte[] keyBytes;
    byte[] ivBytes;

    Now you can initialize the Cipher for the algorithm that you select:
    // wrap key data in Key/IV specs to pass to cipher
    SecretKeySpec key = new SecretKeySpec(keyBytes, "DES");
    IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
    // create the cipher with the algorithm you choose
    // see javadoc for Cipher class for more info, e.g.
    Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

    Encryption would go like this:
    cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
    byte[] encrypted= new byte[cipher.getOutputSize(input.length)];
    int enc_len = cipher.update(input, 0, input.length, encrypted, 0);
    enc_len += cipher.doFinal(encrypted, enc_len);

    And decryption like this:
    cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
    byte[] decrypted = new byte[cipher.getOutputSize(enc_len)];
    int dec_len = cipher.update(encrypted, 0, enc_len, decrypted, 0);
    dec_len += cipher.doFinal(decrypted, dec_len);

  2. This is the first page that shows up via google, and the security
    vulnerabilities in all the implementations make me cringe so I’m
    posting this to add information regarding encryption for others as it
    has been 7 Years from the orignal post. I hold a Masters Degree in
    Computer Engineering and spent a lot of time studying and learning
    Cryptography so I’m throwing my 2 cents in to make the internet a
    safer place.
    Also, do note that a lot of implementation might be secure for a given
    situation, but why use those and potentially accidentally make a
    mistake? Use the strongest tools you have available unless you have a
    specific reason not to. Overall I highly advise using a library and
    staying away from the nitty gritty details if you can. I recommend
    Jasypt.

    I will outline the basics of secure symmetric cryptography below and point out common mistakes I see online.
    First thing first you need to pick a symmetric key Block Cipher. A Block Cipher is a tool used to create Pseudo-Randomness. Make sure to NEVER, I repeat NEVER use DES, I would even say NEVER use 3DES. The only Block Cipher that even Snowden’s NSA release was able to verify being truly as close to Pseudo-Random as possible is AES 256.
    Now let’s talk about encryption modes. Never Use ECB this is bad at hiding repeating data as shown by the famous Linux penguin.
    When implementing in Java note that if you use the following code, ECB mode is set by default:
    Cipher cipher = Cipher.getInstance("AES");
    … AVOID THIS! Which is seen in a a lot of examples online
    If you have no Idea what you are doing I would strictly stick to GCM, and as said before if you really have no idea just use Jasypt. The only other modes that I would even mention are decent as well are CBC and CTR mode, but unlike GCM an attacker could modify the encrypted message in these modes and that is why they are not entirely secure.
    So in the typical java implementation this is the setup you want:
    Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
    GCM is built upon CTR mode and doesn’t require padding. but if for whatever reason you choose to use for example CBC Mode do so with PKCS7Padding as follows:
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
    Another very important note, is that when it comes to cryptography a Key and a Password are not the same things. A Key in cryptography needs to have a certain amount of entropy and randomness to be considered secure. This is why you need to make sure to use the Cryptography libraries Key generating algorithm to pick a key.
    Along with a Key we also have a thing called an IV. While a key is a secret and you should only share it with people you want to be able to decrypt the message, the IV is public. It’s used to make sure that if you encrypt two messages that are the same, the encryption looks different. Now what most people are not aware of is that IV’s can not repeat for the same key. The moment you repeat an IV in modes like GCM, CBC, CTR you actually compromise the entire security of the system. This is why you need to make sure first your IV is not static and that you are using the proper Cryptography library to generate a random IV with a really low probability of accidentally creating two of the same.
    I have by now hopefully gone through all other posts and edited them to take out vulnerabilities. But to make your life easy with Jasypt here is how you use it!
    Gradle
    compile group: 'org.jasypt', name: 'jasypt', version: '1.9.2'
    Setup
    myPassword = "A Strong Password"
    BasicTextEncryptor textEncryptor = new BasicTextEncryptor();
    textEncryptor.setPassword(myPassword);

    Encryption
    String myEncryptedText = textEncryptor.encrypt(myText);
    Decryption
    String plainText = textEncryptor.decrypt(myEncryptedText);
    For more security use the StrongTextEncryptor util class provided below but it is slower. (you may need to download and install the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files to use it):
    Setup
    myPassword = "A Strong Password"
    StrongTextEncryptor textEncryptor = new StrongTextEncryptor();
    textEncryptor.setPassword(myPassword);

    Encryption
    String myEncryptedText = textEncryptor.encrypt(myText);
    Decryption
    String plainText = textEncryptor.decrypt(myEncryptedText);
    Isn’t this just so much cleaner? 🙂
    Note that when using Jasypt you don’t have to worry about the key being truly random as discussed above just use a strong password, their library converts your strong password into a proper crypto key. But remember a weak password is still a weak password
    Android Developers
    One important point to point out here is know that your android code is reverse engineer able. That means if you store the password in plain text in your code. A hacker can easily retrieve it. Usually for these type of encryption you want to use Asymmetric Cryptography and so on. This is outside the scope of this post so I will avoid diving into it.
    An interesting reading from 2013: Points out that 88% of Crypto implementations in android were done improperly and this is really the basis of me coming here and ranting so much.

  3. Warning
    Do not use this as some kind of security measurement.
    The encryption mechanism in this post is a One-time pad, which means that the secret key can be easily recovered by an attacker using 2 encrypted messages. XOR 2 encrypted messages and you get the key. That simple!
    Pointed out by Moussa

    I am using Sun’s Base64Encoder/Decoder which is to be found in Sun’s JRE, to avoid yet another JAR in lib. That’s dangerous from point of using OpenJDK or some other’s JRE. Besides that, is there another reason I should consider using Apache commons lib with Encoder/Decoder?
    public class EncryptUtils {
    public static final String DEFAULT_ENCODING = "UTF-8";
    static BASE64Encoder enc = new BASE64Encoder();
    static BASE64Decoder dec = new BASE64Decoder();

    public static String base64encode(String text) {
    try {
    return enc.encode(text.getBytes(DEFAULT_ENCODING));
    } catch (UnsupportedEncodingException e) {
    return null;
    }
    }//base64encode

    public static String base64decode(String text) {
    try {
    return new String(dec.decodeBuffer(text), DEFAULT_ENCODING);
    } catch (IOException e) {
    return null;
    }
    }//base64decode

    public static void main(String[] args) {
    String txt = "some text to be encrypted";
    String key = "key phrase used for XOR-ing";
    System.out.println(txt + " XOR-ed to: " + (txt = xorMessage(txt, key)));

    String encoded = base64encode(txt);
    System.out.println(" is encoded to: " + encoded + " and that is decoding to: " + (txt = base64decode(encoded)));
    System.out.print("XOR-ing back to original: " + xorMessage(txt, key));
    }

    public static String xorMessage(String message, String key) {
    try {
    if (message == null || key == null) return null;

    char[] keys = key.toCharArray();
    char[] mesg = message.toCharArray();

    int ml = mesg.length;
    int kl = keys.length;
    char[] newmsg = new char[ml];

    for (int i = 0; i < ml; i++) {
    newmsg[i] = (char)(mesg[i] ^ keys[i % kl]);
    }//for i

    return new String(newmsg);
    } catch (Exception e) {
    return null;
    }
    }//xorMessage
    }//class

  4. thanks ive made this class using your code maybe someone finds it userfull
    object crypter
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.security.InvalidAlgorithmParameterException;
    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;

    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.ShortBufferException;
    import javax.crypto.spec.DESKeySpec;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;

    public class ObjectCrypter {

    private Cipher deCipher;
    private Cipher enCipher;
    private SecretKeySpec key;
    private IvParameterSpec ivSpec;

    public ObjectCrypter(byte[] keyBytes, byte[] ivBytes) {
    // wrap key data in Key/IV specs to pass to cipher

    ivSpec = new IvParameterSpec(ivBytes);
    // create the cipher with the algorithm you choose
    // see javadoc for Cipher class for more info, e.g.
    try {
    DESKeySpec dkey = new DESKeySpec(keyBytes);
    key = new SecretKeySpec(dkey.getKey(), "DES");
    deCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
    enCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
    } catch (NoSuchAlgorithmException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (NoSuchPaddingException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (InvalidKeyException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    public byte[] encrypt(Object obj) throws InvalidKeyException, InvalidAlgorithmParameterException, IOException, IllegalBlockSizeException, ShortBufferException, BadPaddingException {
    byte[] input = convertToByteArray(obj);
    enCipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);

    return enCipher.doFinal(input);

    // cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
    // byte[] encypted = new byte[cipher.getOutputSize(input.length)];
    // int enc_len = cipher.update(input, 0, input.length, encypted, 0);
    // enc_len += cipher.doFinal(encypted, enc_len);
    // return encypted;

    }
    public Object decrypt( byte[] encrypted) throws InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, IOException, ClassNotFoundException {
    deCipher.init(Cipher.DECRYPT_MODE, key, ivSpec);

    return convertFromByteArray(deCipher.doFinal(encrypted));

    }

    private Object convertFromByteArray(byte[] byteObject) throws IOException,
    ClassNotFoundException {
    ByteArrayInputStream bais;

    ObjectInputStream in;
    bais = new ByteArrayInputStream(byteObject);
    in = new ObjectInputStream(bais);
    Object o = in.readObject();
    in.close();
    return o;

    }

    private byte[] convertToByteArray(Object complexObject) throws IOException {
    ByteArrayOutputStream baos;

    ObjectOutputStream out;

    baos = new ByteArrayOutputStream();

    out = new ObjectOutputStream(baos);

    out.writeObject(complexObject);

    out.close();

    return baos.toByteArray();

    }

    }

  5. How about this:
    private static byte[] xor(final byte[] input, final byte[] secret) {
    final byte[] output = new byte[input.length];
    if (secret.length == 0) {
    throw new IllegalArgumentException("empty security key");
    }
    int spos = 0;
    for (int pos = 0; pos < input.length; ++pos) {
    output[pos] = (byte) (input[pos] ^ secret[spos]);
    ++spos;
    if (spos >= secret.length) {
    spos = 0;
    }
    }
    return output;
    }

    Works fine for me and is rather compact.

  6. I would consider using something like https://www.bouncycastle.org/ It is a prebuilt library that allows you to encrypt whatever you like with a number of different Ciphers
    I understand that you only want to protect from snooping, but if you really want to protect the information, using Base64 won’t actually protect you.

  7. Here’s my implementation from meta64.com as a Spring Singleton. If you want to create a ciper instance for each call that would work also, and then you could remove the ‘synchronized’ calls, but beware ‘cipher’ is not thread-safe.
    import java.security.Key;

    import javax.crypto.Cipher;
    import javax.crypto.spec.SecretKeySpec;
    import javax.xml.bind.DatatypeConverter;

    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Component;

    @Component
    @Scope("singleton")
    public class Encryptor {

    @Value("${aeskey}")
    private String keyStr;

    private Key aesKey = null;
    private Cipher cipher = null;

    synchronized private void init() throws Exception {
    if (keyStr == null || keyStr.length() != 16) {
    throw new Exception("bad aes key configured");
    }
    if (aesKey == null) {
    aesKey = new SecretKeySpec(keyStr.getBytes(), "AES");
    cipher = Cipher.getInstance("AES");
    }
    }

    synchronized public String encrypt(String text) throws Exception {
    init();
    cipher.init(Cipher.ENCRYPT_MODE, aesKey);
    return toHexString(cipher.doFinal(text.getBytes()));
    }

    synchronized public String decrypt(String text) throws Exception {
    init();
    cipher.init(Cipher.DECRYPT_MODE, aesKey);
    return new String(cipher.doFinal(toByteArray(text)));
    }

    public static String toHexString(byte[] array) {
    return DatatypeConverter.printHexBinary(array);
    }

    public static byte[] toByteArray(String s) {
    return DatatypeConverter.parseHexBinary(s);
    }

    /*
    * DO NOT DELETE
    *
    * Use this commented code if you don't like using DatatypeConverter dependency
    */
    // public static String toHexStringOld(byte[] bytes) {
    // StringBuilder sb = new StringBuilder();
    // for (byte b : bytes) {
    // sb.append(String.format("%02X", b));
    // }
    // return sb.toString();
    // }
    //
    // public static byte[] toByteArrayOld(String s) {
    // int len = s.length();
    // byte[] data = new byte[len / 2];
    // for (int i = 0; i < len; i += 2) {
    // data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i +
    // 1), 16));
    // }
    // return data;
    // }
    }

  8. Here are some links you can read what Java supports
    Encrypting/decrypting a data stream.

    This example demonstrates how to
    encrypt (using a symmetric encryption
    algorithm such as AES, Blowfish, RC2,
    3DES, etc) a large amount of data. The
    data is passed in chunks to one of the
    encrypt methods: EncryptBytes,
    EncryptString, EncryptBytesENC, or
    EncryptStringENC. (The method name
    indicates the type of input (string or
    byte array) and the return type
    (encoded string or byte array). The
    FirstChunk and LastChunk properties
    are used to indicate whether a chunk
    is the first, middle, or last in a
    stream to be encrypted. By default,
    both FirstChunk and LastChunk equal
    true — meaning that the data passed
    is the entire amount.

    JCERefGuide
    Java Encryption Examples

  9. You can use Jasypt
    With Jasypt, encrypting and checking a password can be as simple as…
    StrongTextEncryptor textEncryptor = new StrongTextEncryptor();
    textEncryptor.setPassword(myEncryptionPassword);

    Encryption:
    String myEncryptedText = textEncryptor.encrypt(myText);
    Decryption:
    String plainText = textEncryptor.decrypt(myEncryptedText);
    Gradle:

    compile group: ‘org.jasypt’, name: ‘jasypt’, version: ‘1.9.2’

    Features
    Jasypt provides you with easy unidirectional (digest) and bidirectional encryption techniques.

    Open API for use with any JCE provider, and not only the default Java VM one. Jasypt can be easily used with well-known providers like Bouncy Castle. Learn more.

    Higher security for your users' passwords. Learn more.

    Binary encryption support. Jasypt allows the digest and encryption of binaries (byte arrays). Encrypt your objects or files when needed (for being sent over the net, for example).

    Number encryption support. Besides texts and binaries, it allows the digest and encryption of numeric values (BigInteger and BigDecimal, other numeric types are supported when encrypting for Hibernate persistence). Learn more.

    Completely thread-safe.

    Support for encryptor/digester pooling, in order to achieve high performance in multi-processor/multi-core systems.

    Includes a lightweight ("lite") version of the library for better manageability in size-restrictive environments like mobile platforms.

    Provides both easy, no-configuration encryption tools for users new to encryption, and also highly configurable standard encryption tools, for power-users.

    Hibernate 3 and 4 optional integration for persisting fields of your mapped entities in an encrypted manner. Encryption of fields is defined in the Hibernate mapping files, and it remains transparent for the rest of the application (useful for sensitive personal data, databases with many read-enabled users...). Encrypt texts, binaries, numbers, booleans, dates... Learn more.

    Seamlessly integrable into a Spring application, with specific integration features for Spring 2, Spring 3.0 and Spring 3.1. All the digesters and encryptors in jasypt are designed to be easily used (instantiated, dependency-injected...) from Spring. And, because of their being thread-safe, they can be used without synchronization worries in a singleton-oriented environment like Spring. Learn more: Spring 2, Spring 3.0, Spring 3.1.

    Spring Security (formerly Acegi Security) optional integration for performing password encryption and matching tasks for the security framework, improving the security of your users' passwords by using safer password encryption mechanisms and providing you with a higher degree of configuration and control. Learn more.

    Provides advanced functionality for encrypting all or part of an application's configuration files, including sensitive information like database passwords. Seamlessly integrate encrypted configuration into plain, Spring-based and/or Hibernate-enabled applications. Learn more.

    Provides easy to use CLI (Command Line Interface) tools to allow developers initialise their encrypted data and include encryption/decryption/digest operations in maintenance tasks or scripts. Learn more.

    Integrates into Apache Wicket, for more robust encryption of URLs in your secure applications.

    Comprehensive guides and javadoc documentation, to allow developers to better understand what they are really doing to their data.

    Robust charset support, designed to adequately encrypt and digest texts whichever the original charset is. Complete support for languages like Japanese, Korean, Arabic... with no encoding or platform issues.

    Very high level of configuration capabilities: The developer can implement tricks like instructing an "encryptor" to ask a, for example, remote HTTPS server for the password to be used for encryption. It lets you meet your security needs.

  10. You might want to consider some automated tool to do the encryption / decryption code generation eg. https://www.stringencrypt.com/java-encryption/
    It can generate different encryption and decryption code each time for the string or file encryption.
    It’s pretty handy when it comes to fast string encryption without using RSA, AES etc.
    Sample results:
    // encrypted with https://www.stringencrypt.com (v1.1.0) [Java]
    // szTest = "Encryption in Java!"
    String szTest = "\u9E3F\uA60F\uAE07\uB61B\uBE1F\uC62B\uCE2D\uD611" +
    "\uDE03\uE5FF\uEEED\uF699\uFE3D\u071C\u0ED2\u1692" +
    "\u1E06\u26AE\u2EDC";

    for (int iatwS = 0, qUJQG = 0; iatwS < 19; iatwS++)
    {
    qUJQG = szTest.charAt(iatwS);
    qUJQG ++;
    qUJQG = ((qUJQG << 5) | ( (qUJQG & 0xFFFF) >> 11)) & 0xFFFF;
    qUJQG -= iatwS;
    qUJQG = (((qUJQG & 0xFFFF) >> 6) | (qUJQG << 10)) & 0xFFFF;
    qUJQG ^= iatwS;
    qUJQG -= iatwS;
    qUJQG = (((qUJQG & 0xFFFF) >> 3) | (qUJQG << 13)) & 0xFFFF;
    qUJQG ^= 0xFFFF;
    qUJQG ^= 0xB6EC;
    qUJQG = ((qUJQG << 8) | ( (qUJQG & 0xFFFF) >> 8)) & 0xFFFF;
    qUJQG --;
    qUJQG = (((qUJQG & 0xFFFF) >> 5) | (qUJQG << 11)) & 0xFFFF;
    qUJQG ++;
    qUJQG ^= 0xFFFF;
    qUJQG += iatwS;
    szTest = szTest.substring(0, iatwS) + (char)(qUJQG & 0xFFFF) + szTest.substring(iatwS + 1);
    }

    System.out.println(szTest);
    We use it all the time in our company.

  11. String s1="arshad";
    char[] s2=s1.toCharArray();
    int s3= s2.length;

    System.out.println(s3);
    int i=0;

    // for(int j=0;j<s3;j++)
    // System.out.println(s2[j]);

    for(i=0;i<((s3)/2);i++) {

    char z,f=10;
    z=(char) (s2[i] * f);
    s2[i]=s2[(s3-1)-i];
    s2[(s3-1)-i]=z;

    String b=new String(s2);

    print(b); }

  12. public static String encryptParams(String myTextInput) {

    String myKey = "40674244454045cb9a70040a30e1c007";
    String myVector = "@1B2c3D4e5F6g7H8";

    String encData = "";

    try{
    JavaEncryprtionUtil encUtil = new JavaEncryprtionUtil();
    encData = Base64.encodeToString(encUtil.encrypt(myTextInput.getBytes("UTF-8"), myKey.getBytes("UTF-8"), myVector.getBytes("UTF-8")),Base64.DEFAULT);
    System.out.println(encData);
    }catch(NoSuchAlgorithmException ex){
    ex.printStackTrace();
    }catch(NoSuchPaddingException ex){
    ex.printStackTrace();
    }catch(InvalidKeyException ex){
    ex.printStackTrace();
    }catch(InvalidAlgorithmParameterException ex){
    ex.printStackTrace();
    }catch(IllegalBlockSizeException ex){
    ex.printStackTrace();
    }catch(BadPaddingException ex){
    ex.printStackTrace();
    }catch(UnsupportedEncodingException ex){
    ex.printStackTrace();
    }

    return encData;
    }

Leave a Reply

Your email address will not be published.