Migrate String encryption from Ruby to Java - java

I need to produce the same encrypted string in Java as the one built with the Ruby encrypted_strings library. I've tried many different ways but my Java code keeps returning a different output, and I'm unable to understand what I'm doing wrong.
Below is the ruby script that produces the desired output that I can't get right in Java.
#!/usr/bin/ruby
require 'encrypted_strings'
data = 'Whackabad'
password = 'bAJLyifeUJUBFWdHzVbykfDmPHtLKLMzViHW9aHGmyTLD8hGYZ'
encrypted_data = data.encrypt(:symmetric, :password => password)
printf "Data: #{data}\n"
printf "Encrypted Data: #{encrypted_data}"
Output:
Data: Whackabad
Encrypted Data: AEsDXVcgh2jsTjlDgh+REg==
I had a look at the library, and it seems to be using DES-EDE3-CBC as the default algorithm for encryption. I deduce from here that I should use DESede or TripleDES algorithm and CBC mode. As the padding option, I'm using PKCS5Padding cause the library is calling pkcs5_keyivgen.
Below is the Java code that tries to reproduce the same output unsuccessfully.
package ...
import sun.misc.BASE64Encoder;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
public class SymmetricDESedeCipher {
private static final String DATA = "Whackabad";
private static final String key = "bAJLyifeUJUBFWdHzVbykfDmPHtLKLMzViHW9aHGmyTLD8hGYZ";
private static final String ALGORITHM = "DESede";
private static final String XFORM = "DESede/CBC/PKCS5Padding";
private static byte[] iv = new byte[8];
private static byte[] encrypt(byte[] inpBytes,
SecretKey key, String XFORM) throws Exception {
Cipher cipher = Cipher.getInstance(XFORM);
IvParameterSpec ips = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, ips);
return cipher.doFinal(inpBytes);
}
public static void main(String[] unused) throws Exception {
byte[] keyBytes = key.getBytes();
DESedeKeySpec desKeySpec = new DESedeKeySpec(keyBytes);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
byte[] dataBytes = DATA.getBytes();
byte[] encBytes = encrypt(dataBytes, secretKey, XFORM);
System.out.println("Data: " + DATA);
System.out.println("Encrypted Data: " + new BASE64Encoder().encode(encBytes));
}
}
Output
Data: Whackabad
Encrypted Data: ScPTKQBsR9Ni1nJ1tsMaaQ==
I've seen people encrypting data from Java to be decrypted from Ruby and vice-versa with different algorithms so I think this can be achieved but I can't see what's wrong. Do you have an idea? If so, that'd be of much help!
Thanks

The first thing to do is to derive the IV and key from the given password.
From the link above, you will get an encoded IV and KEY that corresponds with "VDiJjncs4ak=" and "s9e42J3PpmQv8n5T8L3zzuFaGdrzK/wU" respectively.
This means that the key and IV vector used in the Java code are wrong as it was said in the comments.
Below is the resulting Java code:
public class SymmetricDESedeCipher {
private static final String DATA = "Whackabad";
private static final String ALGORITHM = "DESede";
private static final String XFORM = "DESede/CBC/PKCS5Padding";
private static final String KEY = "s9e42J3PpmQv8n5T8L3zzuFaGdrzK/wU";
private static final String IV = "VDiJjncs4ak=";
private static byte[] encrypt(String data,
SecretKey key, String XFORM, byte[] iv) throws Exception {
Cipher cipher = Cipher.getInstance(XFORM);
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
return cipher.doFinal(data.getBytes());
}
public static void main(String[] unused) throws Exception {
DESedeKeySpec spec = new DESedeKeySpec(new BASE64Decoder().decodeBuffer(KEY));
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey secretKey = secretKeyFactory.generateSecret(spec);
byte[] encBytes = encrypt(DATA, secretKey, XFORM, new BASE64Decoder().decodeBuffer(IV));
System.out.println("Data: " + DATA);
System.out.println("Encrypted Data: " + new BASE64Encoder().encode(encBytes));
}
}
Output:
Data: Whackabad
Encrypted Data: AEsDXVcgh2jsTjlDgh+REg==

Related

Password too short using AES/CFB/NoPadding, AES/OFB/NoPadding or AES/ CBC/NoPadding

Can someone help me reinforce or improve the following code to make the resulting passwords "longer".
I am humbly looking for the best way to use AES/CFB/NoPadding, or with AES/CBC/NoPadding, or with AES/OFB/NoPadding. We have tested with AES/GCM/NOPADDING. Which works with Java 8, but not with Java 7. And we need something that works in Java 7
For example, using 'safe' as <key_to_encrypt>, and 'Bk206V4ytQ1zZAukPE6/2c5KUcxGYpBf' as <encryption_key>, the pwd is: FX5O5A==
which is quite bite "small"
import java.security.MessageDigest;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.xml.security.utils.Base64;
public class StringEncrypt {
private final static String ALG = "AES";
private final static String CI = "AES/CFB/NoPadding";
public static String encrypt(String cleartext, String key) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(key.getBytes());
IvParameterSpec iv = new IvParameterSpec(md.digest());
Cipher cipher = Cipher.getInstance(CI);
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), ALG);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(cleartext.getBytes());
return new String(Base64.encode(encrypted));
}
public static String decrypt(String encrypted, String key) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(key.getBytes());
IvParameterSpec iv = new IvParameterSpec(md.digest());
Cipher cipher = Cipher.getInstance(CI);
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), ALG);
byte[] enc = Base64.decode(encrypted);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] decrypted = cipher.doFinal(enc);
return new String(decrypted);
}
public static void main(String[] args) throws Exception {
if (args.length == 2) {
String pwd = StringEncrypt.encrypt(args[0], args[1]);
System.out.println("Key encryption: " + pwd);
pwd = StringEncrypt.decrypt(pwd, args[1]);
if (args[0].equals(pwd)) {
System.out.println("[OK] Correct decryption!");
} else {
System.out.println("[KO] Wrong decryption!");
}
} else {
System.out.println("The parameters are required: <key_to_encrypt> <encryption_key>");
}
}
}
Stated differently, could someone give me an example of good encryption / decryption that works in Java 7?
If you want to increase the length, you need to increase the byte count of the encrypted / decrypted parameter.
You could hack this by changing the charset although I don't think is best practice:
byte[] encrypted = cipher.doFinal(cleartext.getBytes(StandardCharsets.UTF_16));
return new String(decrypted, StandardCharsets.UTF_16);

BadPaddingException just with letters like "o", "b", "c"

I'm making a program which works with messages cryptography by Socket. But, when in my messages has a "o", or "b", or "c" and another letters, i receives that Exception in the decrypto moment.
Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
at com.sun.crypto.provider.CipherCore.unpad(CipherCore.java:975)
at com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1056)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:853)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
at javax.crypto.Cipher.doFinal(Cipher.java:2164)
at teste1.Decrypt.decrypt(Decrypt.java:15)
at teste1.Server.main(Server.java:24)
Yep, my message arrives completed with all the characters, so i don't think in some character was lost in the trasmission. So i don't really know what's the problem, because i've tried to changes a lot of things, but i continued recieving this Exception.
Decrypt class:
package teste1;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
public class Decrypt{
String IV = "AAAAAAAAAAAAAAAA";
public String decrypt(String str, String keys) throws Exception{
Cipher decrypt = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(keys.getBytes("UTF-8"), "AES");
decrypt.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(IV.getBytes("UTF-8")));
return new String(decrypt.doFinal(str.getBytes()),"UTF-8");
}
}
If wants the encrypt class too:
package teste1;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Encrypt {
String IV = "AAAAAAAAAAAAAAAA";
public byte[] encrypt(String menE, String keys) throws Exception {
Cipher encrypt = Cipher.getInstance("AES/EBC/PKCS5Padding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(keys.getBytes("UTF-8"), "AES");
encrypt.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV.getBytes("UTF-8")));
return encrypt.doFinal(menE.getBytes());
}
}
That happens because Strings change your bytes, you should really use Base64
if strings are a must.
If you want to test that run this code:
byte[] aByte = {-45};
System.out.println(Arrays.toString(new String(aByte, StandardCharsets.UTF_8).getBytes(StandardCharsets.UTF_8)));
It will output: [-17, -65, -67] (which is not -45).
Anyways so a few tips for you:
You cannot encrypt with "ECB" and decrypt with "CBC".
An IV should not be a constant. you should generate a new IV for every message and send it along with the message.
Don't specify "UTF-8" use StandardCharsets.UTF_8 (note if using android: StandardCharsets.UTF-8 is API 19+ so you should have a constant for Charset.forName("UTF-8"))
Here is some example code for how to do it with Base64:
public byte[] encrypt(String message, String key, String iv) throws Exception {
Cipher encrypt = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
SecretKeySpec secretKey = new SecretKeySpec(Base64.getDecoder().decode(key), "AES");
encrypt.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(Base64.getDecoder().decode(iv)));
return encrypt.doFinal(/*Get bytes from your message*/message.getBytes(StandardCharsets.UTF_8));
}
public String decrypt(String encryptedMessage, String key, String iv) throws Exception{
Cipher decrypt = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
SecretKeySpec secretKey = new SecretKeySpec(Base64.getDecoder().decode(key), "AES");
decrypt.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(Base64.getDecoder().decode(iv)));
return new String(decrypt.doFinal(Base64.getDecoder().decode(encryptedMessage)), StandardCharsets.UTF_8);
}
And run it with
//your message
String message = "Hello World!";
//generate a new AES key. (an AES key is just a random sequence 16 bytes)
SecureRandom random = new SecureRandom();
byte[] aesKey = new byte[16];
random.nextBytes(aesKey);
//generate a new initialization vector (iv) which is also a random sequence of 16 bytes.
byte[] iv = new byte[16];
random.nextBytes(iv);
String aesKeyAsString = Base64.getEncoder().encodeToString(aesKey);
String ivAsString = Base64.getEncoder().encodeToString(iv);
//encrypt
byte[] encrypted = encrypt(message, aesKeyAsString, ivAsString);
//enocde your encrypted byte[] to String
String encryptedString = Base64.getEncoder().encodeToString(encrypted);
//decrypt
String decrypted = decrypt(encryptedString, aesKeyAsString, ivAsString);
//print your results
System.out.println("Encrypted: " + encryptedString + " Decrypted: " + decrypted);
Outputs:
Encrypted: |encrypted string depended on the generated key and iv| Decrypted: Hello World!
You can also use the more efficient way and use byte[] instead of Strings but it's your choice.

AES-128 Encrypted String not properly padded

I'm having trouble creating an encrypted string using AES/CBC/PKCS5Padding with a 128-bit key. I have code to decrypt an encrypted string. I have an example encrypted string from another system that decrypts successfully, but when I try to create my own encrypted string it is not padded properly for some reason. When I decrypt my encrypted string it only shows the characters after the 16 byte.
All of the examples I find either assume the encryption happens first then decryption happens right after that with variables set during encryption or they are randomly generating a key, but in my case i want to use a known key.
I am really stuck so any help would be greatly appreciated, thank you very much for your time and efforts!
Example:
Original Text: 01234567891234565
Encrypted: zmb16qyYrdoW6akBdcJv7DXCzlw0qU7A2ea5q4YQWUo=
Key length: 16
Decrypted: 5 (this is the last digit in the Original Text String)
Sample Code:
package com.company.encrypt.tests;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
public class TestEncryptDecrypt {
private static final String characterEncoding = "UTF-8";
private static final String cipherTransformation = "AES/CBC/PKCS5Padding";
private static final String aesEncryptionAlgorithm = "AES";
public static void main(String[] args) throws Exception {
String key1 = "1234567812345678";
String text = "01234567891234565";
System.out.println("Original Text: " + text);
String encrypted = encrypt(text, key1);
System.out.println("Encrypted: " + encrypted);
String decrypted = decrypt(encrypted, key1);
System.out.println("Decrypted: " + decrypted);
}
public static String decrypt(String encryptedText, String key) throws Exception {
String plainText = null;
int keyLength = key.length();
System.out.println("Key length: " + String.valueOf(keyLength));
byte[] encryptedTextBytes = Base64.decodeBase64(encryptedText.getBytes());
byte[] keyBytes = key.getBytes();
byte[] initialVector = Arrays.copyOfRange(encryptedTextBytes, 0, keyLength);
byte[] trimmedCipherText = Arrays.copyOfRange(encryptedTextBytes, keyLength, encryptedTextBytes.length);
try {
Cipher cipher = Cipher.getInstance(cipherTransformation);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, aesEncryptionAlgorithm);
IvParameterSpec ivParameterSpec = new IvParameterSpec(initialVector);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] clearText;
clearText = cipher.doFinal(trimmedCipherText);
plainText = new String(clearText, characterEncoding);
} catch(NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException
| InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return plainText;
}
public static String encrypt(String plainText, String encryptionKey) throws Exception {
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), aesEncryptionAlgorithm);
Cipher cipher = Cipher.getInstance(cipherTransformation);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] plainTextBytes = plainText.getBytes("UTF-8");
byte[] encrypted = cipher.doFinal(plainTextBytes);
return new String(Base64.encodeBase64(encrypted));
}
}
I've noticed that in the decrypt() function, you separated the encrypted array into two parts: first 16 bytes, and the rest. You used the first 16 bytes as the IV for decryption, however, you did not prepend the 16 byte IV to the beginning of the encrypted message in encrypt(). This results in the first 16 bytes of the plaintext to be lost. I presume you assumed that doFinal() automatically does that for you, but it doesn't.
To fix this, before returning the encrypted message, prepend the IV, which can be retrieved using cipher.getIV(). You can accomplish this using the ArrayUtils.addAll() from Apache Commons Lang library, or simply write your own function to do it. Another thing to note is that the IV will always be the block size, which is 16 bytes for AES, no matter the key size.
Hope this answer helps!

Java AES String decrypting "given final block not properly padded"

For all haters, I READ MANY topics like this one, and non of them was helpful.
eg. here javax.crypto.BadPaddingException: Given final block not properly padded error while decryption or here Given final block not properly padded
I want to encrypt and then decrypt Strings. Read many topics about
"Given final block not properly padded" exception, but non of these solutions worked.
My Class:
package aes;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.swing.JOptionPane;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
public class EncryptionExample {
private static SecretKeySpec key;
private static IvParameterSpec ivSpec;
private static Cipher cipher;
private static byte[] keyBytes;
private static byte[] ivBytes;
private static int enc_len;
public static void generateKey() throws Exception
{
String complex = new String ("9#82jdkeo!2DcASg");
keyBytes = complex.getBytes();
key = new SecretKeySpec(keyBytes, "AES");
complex = new String("#o9kjbhylK8(kJh7"); //just some randoms, for now
ivBytes = complex.getBytes();
ivSpec = new IvParameterSpec(ivBytes);
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
}
public static String encrypt(String packet) throws Exception
{
byte[] packet2 = packet.getBytes();
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] encrypted = new byte[cipher.getOutputSize(packet2.length)];
enc_len = cipher.update(packet2, 0, packet2.length, encrypted, 0);
enc_len += cipher.doFinal(encrypted, enc_len);
return packet = new String(encrypted);
}
public static String decrypt(String packet) throws Exception
{
byte[] packet2 = packet.getBytes();
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] decrypted = new byte[cipher.getOutputSize(enc_len)];
int dec_len = cipher.update(packet2, 0, enc_len, decrypted, 0);
HERE EXCEPTION>>>>> dec_len += cipher.doFinal(decrypted, dec_len); <<<<<<<<<
return packet = new String(decrypted);
}
// and display the results
public static void main (String[] args) throws Exception
{
// get the text to encrypt
generateKey();
String inputText = JOptionPane.showInputDialog("Input your message: ");
String encrypted = encrypt(inputText);
String decrypted = decrypt(encrypted);
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
"Encrypted: " + new String(encrypted) + "\n"
+ "Decrypted: : " + new String(decrypted));
.exit(0);
}
}
The thing is, when I decrypt strings (about 4/10 of shots), I get that exception:
Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:479)
at javax.crypto.Cipher.doFinal(Cipher.java:2068)
at aes.EncryptionExample.deszyfrujBez(EncryptionExample.java:HERE tag)
at aes.EncryptionExample.main(EncryptionExample.java:Main starting)
Does anybody know what to change here (key? *.doFinal() method?) to make it work?
# for those curious - methods have to be static, as this is a part of something bigger ;)
When you use byte[] packet2 = packet.getBytes() you are converting the string based on the default encoding, which could be UTF-8, for example. That's fine. But then you convert the ciphertext back to a string like this: return packet = new String(encrypted) and this can get you into trouble if this does not round-trip to the same byte array later in decrypt() with another byte[] packet2 = packet.getBytes().
Try this instead: return packet = new String(encrypted, "ISO-8859-1"), and byte[] packet2 = packet.getBytes("ISO-8859-1") -- it's not what I would prefer, but it should round-trip the byte arrays.
The result of encryption is binary data. In most cases it cannot be interpreted as a valid string encoding. So the call to new String(encrypted) will most likely distort the encrypted bytes and after doing packet.getBytes() you end up with a byte array with different content.
The decryption now fails because the cypher text has been changed. The padding bytes are not correctly recovered and cannot be removed.
To fix that, don't convert the cypher text to a string, keep the byte array.

Java BouncyCastle Cast6Engine (CAST-256) encrypting

I'm trying to implement a function that receives a string and returns the encoded values of the String in CAST-256. The following code is what i implement following the example on BoncyCastle official web page (http://www.bouncycastle.org/specifications.html , point 4.1).
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.engines.CAST6Engine;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
public class Test {
static{
Security.addProvider(new BouncyCastleProvider());
}
public static final String UTF8 = "utf-8";
public static final String KEY = "CLp4j13gADa9AmRsqsXGJ";
public static byte[] encrypt(String inputString) throws UnsupportedEncodingException {
final BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CAST6Engine());
byte[] key = KEY.getBytes(UTF8);
byte[] input = inputString.getBytes(UTF8);
cipher.init(true, new KeyParameter(key));
byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
int outputLen = cipher.processBytes(input, 0, input.length, cipherText, 0);
try {
cipher.doFinal(cipherText, outputLen);
} catch (CryptoException ce) {
System.err.println(ce);
System.exit(1);
}
return cipherText;
}
public static void main(String[] args) throws UnsupportedEncodingException {
final String toEncrypt = "hola";
final String encrypted = new String(Base64.encode(test(toEncrypt)),UTF8);
System.out.println(encrypted);
}
}
But , when i run my code i get
QUrYzMVlbx3OK6IKXWq1ng==
and if you encode hola in CAST-256 with the same key ( try here if you want http://www.tools4noobs.com/online_tools/encrypt/) i should get
w5nZSYEyA8HuPL5V0J29Yg==.
What is happening? Why im getting a wront encrypted string?
I'm tired of find that on internet and didnt find a answer.
Bouncy Castle uses PKCS #7 padding by default, while PHP's mcrypt (and the web site you linked) uses zero padding by default. This causes the different ciphertexts.
Please note that the ECB mode used here is not secure for almost any use. Additionally, I hope the secret key you posted is not the real key, because now that it's not secret anymore, all this encryption is useless.
This doesn't really answer your question, but it does provide some pointers.
You need to do a little digging to ensure you are decrypting in exactly the same way as PHP's mcrypt(). You need to make sure your key generation, encoding/decoding and cipher algorithm match exactly.
Keys
"CLp4j13gADa9AmRsqsXGJ".getBytes("UTF-8");
is probably not the right way to create the key source bytes. The docs seem to indicate that mcrypt() pads the key and data with \0 if it isn't the right size. Note that your method produces a 168 bit key, which is not a valid key size and I'm not sure what java is going to do about it.
Algorithm
Make sure the cipher mode and padding are the same. Does mcrypt() use ECB, CBC, something else?
Encoding
Ciphers work on bytes, not Strings. Make sure your conversion between the two is the same in java and PHP.
Here is a reference test for CAST6 using test vectors from https://www.rfc-editor.org/rfc/rfc2612#page-10. Note the key, ciphertext and plaintext are hex encoded.
import java.security.Provider;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class Cast6 {
static final String KEY_ALGO = "CAST6";
static final String CIPHER_ALGO = "CAST6/ECB/NOPADDING";
static String keytext = "2342bb9efa38542c0af75647f29f615d";
static String plaintext = "00000000000000000000000000000000";
static String ciphertext = "c842a08972b43d20836c91d1b7530f6b";
static Provider bc = new BouncyCastleProvider();
public static void main(String[] args) throws Exception {
System.out.println("encrypting");
String actual = encrypt();
System.out.println("actual: " + actual);
System.out.println("expect: " + ciphertext);
System.out.println("decrypting");
actual = decrypt();
System.out.println("actual: " + actual);
System.out.println("expect: " + plaintext);
}
static String encrypt() throws Exception {
Cipher cipher = Cipher.getInstance(CIPHER_ALGO, bc);
byte[] keyBytes = Hex.decodeHex(keytext.toCharArray());
SecretKeySpec key = new SecretKeySpec(keyBytes, KEY_ALGO);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] input = Hex.decodeHex(plaintext.toCharArray());
byte[] output = cipher.doFinal(input);
String actual = Hex.encodeHexString(output);
return actual;
}
static String decrypt() throws Exception {
Cipher cipher = Cipher.getInstance(CIPHER_ALGO, bc);
byte[] keyBytes = Hex.decodeHex(keytext.toCharArray());
SecretKeySpec key = new SecretKeySpec(keyBytes, KEY_ALGO);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] output = cipher.doFinal(Hex.decodeHex(ciphertext.toCharArray()));
String actual = Hex.encodeHexString(output);
return actual;
}
}

Categories