Vigenère cipher in Java for all UTF-8 characters

I have this simple function to encrypt strings through Vigenère in Java. I skipped decryption, as it is just a "-" instead of a "+" in the line where the new value is calculated.

But this function only works for the normal alphabet AZ. How to change a function so that it supports lowercase letters, as well as uppercase letters and all other UTF-8 characters?

public static String vigenere_encrypt(String plaintext, String key) { String encryptedText = ""; for (int i = 0, j = 0; i < plaintext.length(); i++, j++) { if (j == key.length()) { j = 0; } // use key again if end reached encryptedText += (char) ((plaintext.charAt(i)+key.charAt(j)-130)%26 + 65); } return encryptedText; } 

Many thanks for your help!

+2
source share
3 answers

The other answer that Vigenere makes for upper and lower case characters is simply inserting other characters. Use this method to create multiple character groups for encoding.

 public static String vigenere(String plaintext, String key, boolean encrypt) { final int textSize = plaintext.length(); final int keySize = key.length(); final int groupSize1 = 'Z' - 'A' + 1; final int groupSize2 = 'z' - 'a' + 1; final int totalGroupSize = groupSize1 + groupSize2; final StringBuilder encryptedText = new StringBuilder(textSize); for (int i = 0; i < textSize; i++) { final char plainChar = plaintext.charAt(i); // this should be a method, called for both the plain text as well as the key final int plainGroupNumber; if (plainChar >= 'A' && plainChar <= 'Z') { plainGroupNumber = plainChar - 'A'; } else if (plainChar >= 'a' && plainChar <= 'z') { plainGroupNumber = groupSize1 + plainChar - 'a'; } else { // simply leave spaces and other characters encryptedText.append(plainChar); continue; } final char keyChar = key.charAt(i % keySize); final int keyGroupNumber; if (keyChar >= 'A' && keyChar <= 'Z') { keyGroupNumber = keyChar - 'A'; } else if (keyChar >= 'a' && keyChar <= 'z') { keyGroupNumber = groupSize1 + keyChar - 'a'; } else { throw new IllegalStateException("Invalid character in key"); } // this should be a separate method final int cipherGroupNumber; if (encrypt) { cipherGroupNumber = (plainGroupNumber + keyGroupNumber) % totalGroupSize; } else { // some code to go around the awkward way of handling % in Java for negative numbers final int someCipherGroupNumber = plainGroupNumber - keyGroupNumber; if (someCipherGroupNumber < 0) { cipherGroupNumber = (someCipherGroupNumber + totalGroupSize); } else { cipherGroupNumber = someCipherGroupNumber; } } // this should be a separate method final char cipherChar; if (cipherGroupNumber < groupSize1) { cipherChar = (char) ('A' + cipherGroupNumber); } else { cipherChar = (char) ('a' + cipherGroupNumber - groupSize1); } encryptedText.append(cipherChar); } return encryptedText.toString(); } 

Again, this is an unsafe code, because the cipher used has been broken for centuries. Do not use too many "A" characters in your keys :) But the character encoding should be sound.

+3
source

Well, you asked for it, and I felt puzzled, but I printed the encryption text and you find out what you just asked for ...

 public static String vigenereUNICODE(String plaintext, String key, boolean encrypt) { final int textSize = plaintext.length(); final int keySize = key.length(); final StringBuilder encryptedText = new StringBuilder(textSize); for (int i = 0; i < textSize; i++) { final int plainNR = plaintext.codePointAt(i); final int keyNR = key.codePointAt(i % keySize); final long cipherNR; if (encrypt) { cipherNR = ((long) plainNR + (long) keyNR) & 0xFFFFFFFFL; } else { cipherNR = ((long) plainNR - (long) keyNR) & 0xFFFFFFFFL; } encryptedText.appendCodePoint((int) cipherNR); } return encryptedText.toString(); } 

EDIT: Please never use in production code, as I have no clue whether the codes can actually be encoded / decoded. As far as I know, not all points have been defined, but the standard is a moving target.

+4
source

If full unicode support is not possible, and you must define your list of valid characters, anyway, why not just use such a function?

 public static String vigenere_cipher(String plaintext, String key, boolean encrypt) { String alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ,.-"; // including some special chars final int alphabetSize = alphabet.length(); final int textSize = plaintext.length(); final int keySize = key.length(); final StringBuilder encryptedText = new StringBuilder(textSize); for (int i = 0; i < textSize; i++) { final char plainChar = plaintext.charAt(i); // get the current character to be shifted final char keyChar = key.charAt(i % keySize); // use key again if the end is reached final int plainPos = alphabet.indexOf(plainChar); // plain character position in alphabet string if (plainPos == -1) { // if character not in alphabet just append unshifted one to the result text encryptedText.append(plainChar); } else { // if character is in alphabet shift it and append the new character to the result text final int keyPos = alphabet.indexOf(keyChar); // key character position in alphabet string if (encrypt) { // encrypt the input text encryptedText.append(alphabet.charAt((plainPos+keyPos) % alphabetSize)); } else { // decrypt the input text int shiftedPos = plainPos-keyPos; if (shiftedPos < 0) { // negative numbers cannot be handled with modulo shiftedPos += alphabetSize; } encryptedText.append(alphabet.charAt(shiftedPos)); } } } return encryptedText.toString(); } 

This should be a very short and working version. And the alphabet can be easily saved in a line that can always be expanded (which leads to different encrypted texts).

+2
source

Source: https://habr.com/ru/post/919776/


All Articles