HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

DIY String Encryption

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
encryptiondiystring

Problem

I was asked to make a String encryption utility without using encryption API. I basically had to come up with my own encryption methodology! the program was to be able to encrypt a string and decrypt a string and to of course make it nearly impossible for anyone to figure out what the encrypted string says!

I would really love to once again get some advice and suggestions regarding my code! I know it is not fast and could indeed be faster but that wasnt the main focus in this case!

This question is related to String Encryption
which is a previous post made by me regarding this question. I was advised to make another question for another round of reviews so here it goes. I try to follow nearly all of the recommendations given by the community and this is the end result.

The question is now. would you consider this encryption method to be safe? meaning: is it hard to break the encryption without knowing the keys and patterns used behind it? why and why not?

```
import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
* String Encrypter
*
* This programs allows you encrypt a string and store as a byte array.
* the program provides a simple encryption set of methods which make use of
* scrambling/adding/replacing/swapping/ the core structure of the string.
* The encrypted message is the store as byte array object which can be sent through sockets
* or stored locally. In order to be able to view the content of the string the object
* must be passed through the decrypt method of this program which will format and reconstruc the
* string to it's original state.
*
* If the message is infiltrated while stored as an encrypted byte array whether if it is traveling
* through a socket or store locally on a system. the thief wont be able to see
* the content of the message without the key used b

Solution

In encryption, never provide a default key. People will use it without thinking further, and the default key will be known to anyone using your code.

When you are given a wrong key, do not silently ignore it. Throw an exception instead. Combined with the default key above, this would lead to no encryption at all.

Even better, make it impossible to provide a wrong key. Instead, accept a password and compute a correct key from this password. For example, like this:

/* Choose a fixed SecureRandom algorithm to be able to decrypt the ciphertext later on. */
SecureRandom getSha1Prng() {
  try {
    return SecureRandom.getInstance("SHA1PRNG");
  } catch (NoSuchAlgorithmException e) {
    throw new IllegalStateException(e);
  }
}

String generateKey(String password) {
  SecureRandom random = getSha1Prng();
  random.setSeed(password.getBytes(StandardCharsets.UTF_8));

  List keyCodePoints = "abcdefghijklmnopqrstuvwxyzåäö0123456789".codePoints().boxed().collect(Collectors.toList());
  Collections.shuffle(keyCodePoints, random);

  StringBuilder sb = new StringBuilder();
  for (Integer codePoint : keyCodePoints)
    sb.appendCodePoint(codePoint);
  return sb.toString();
}

@Test
public void test() {
  assertEquals("l7nw1y9uz5jqk03vfoåmpäis84hdbegtöxr62ac", generateKey(""));
  assertEquals("06o3yd2äz7belfö9h8ucjisgmpqkrwa4tx5ånv1", generateKey("1"));
  assertEquals("afms5qånye7r9wxö1tcj8i3k4ou0hg6l2vzäpdb", generateKey("2"));
  assertEquals("åö7nwib26zlhk9g3amy4s5fvxec1pqjod8ä0utr", generateKey("3"));
  assertEquals("8nqlseph5fat1vöki4x03cyuz6gbmwä7doå9j2r", generateKey("4"));
}


Check that when you change a single character in the plaintext or in the key, the encrypted message looks totally different.

Code Snippets

/* Choose a fixed SecureRandom algorithm to be able to decrypt the ciphertext later on. */
SecureRandom getSha1Prng() {
  try {
    return SecureRandom.getInstance("SHA1PRNG");
  } catch (NoSuchAlgorithmException e) {
    throw new IllegalStateException(e);
  }
}

String generateKey(String password) {
  SecureRandom random = getSha1Prng();
  random.setSeed(password.getBytes(StandardCharsets.UTF_8));

  List<Integer> keyCodePoints = "abcdefghijklmnopqrstuvwxyzåäö0123456789".codePoints().boxed().collect(Collectors.toList());
  Collections.shuffle(keyCodePoints, random);

  StringBuilder sb = new StringBuilder();
  for (Integer codePoint : keyCodePoints)
    sb.appendCodePoint(codePoint);
  return sb.toString();
}

@Test
public void test() {
  assertEquals("l7nw1y9uz5jqk03vfoåmpäis84hdbegtöxr62ac", generateKey(""));
  assertEquals("06o3yd2äz7belfö9h8ucjisgmpqkrwa4tx5ånv1", generateKey("1"));
  assertEquals("afms5qånye7r9wxö1tcj8i3k4ou0hg6l2vzäpdb", generateKey("2"));
  assertEquals("åö7nwib26zlhk9g3amy4s5fvxec1pqjod8ä0utr", generateKey("3"));
  assertEquals("8nqlseph5fat1vöki4x03cyuz6gbmwä7doå9j2r", generateKey("4"));
}

Context

StackExchange Code Review Q#138972, answer score: 5

Revisions (0)

No revisions yet.