Hashing using SHA 256 and encrypting using AES - java

In order for me to consume a webservice, I need to generate a value for an header named Authorization. The steps to generate the header is as follows:
1. Hash Generation
HashValue = SHA2(username, password, id)
2. Auth Key Generation
Authkey = AES(Salt + anotherId + "=" + HashValue)
These are the algorithms details:
Algorithm - AES
Mode - ECB
Padding - PKCS5Padding
Secret key - someString
Now I will be performing the AES encryption using the above details and the secret key which is a string.
After the encryption, I will use the above generated encrypted value as a header in my rest service call.
I have done this so far:
String username = "username";
String password = "password";
String id = "123456";
String toBeHashed = username + password + id;
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
byte[] hashed = sha256.digest(toBeHashed.getBytes("UTF-8"));
String hashString = "=" + Base64.encodeBase64String(hashed);
System.out.println(hashString);
String salt = "salt";
String anotherId = "123";
byte[] forAuth = (salt + orgId + hashString).getBytes("UTF-8");
//Mocked "secret key". Original key string is of size 16 bytes.
byte[] secKey = "secret key".getBytes("UTF-8");
SecretKey secretKey = new SecretKeySpec(secKey, 0, secKey.length, "AES");
Cipher aesCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
aesCipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] authorizationKey = aesCipher.doFinal(forAuth);
System.out.println("-------------------");
System.out.println("-------------------");
System.out.println(Base64.encodeBase64String(authorizationKey));
But still the backend service says that my authorization key is invalid. Please tell me if I am missing something.

**Encrypt and Decrypt using AES**
public static String encrypt(String value) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
IvParameterSpec iv = new IvParameterSpec("randomStringVec".getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec("randomStringKey".getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(1, skeySpec, iv);
byte[] encrypted = cipher.doFinal(value.getBytes());
return Base64.encodeBase64String(encrypted);
}
public static String decrypt(String encrypted) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
IvParameterSpec iv = new IvParameterSpec("randomStringVec".getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec("randomStringKey".getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(2, skeySpec, iv);
byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));
return new String(original);
}
**Encryption Using SHA256**
private static String encrypt256(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest crypt = MessageDigest.getInstance("SHA-256");
crypt.reset();
crypt.update(password.getBytes("UTF-8"));
return new BigInteger(1, crypt.digest()).toString(16);
}

You need to change this:
String hashString = "=" + Base64.encodeBase64String(hashed);
System.out.println(hashString);
To:
String hashString = "=" + new String(hashed);
System.out.println(hashString);
Since the hashed key is getting base64encoded before the authorization key generation.

Related

bad base64 error during decrypting on AES

I'm trying to encrypt and decrypt some text using AES algorithm like :
private static final String ALGORITHM = "AES";
private static final String MODE = "AES/CBC/PKCS7Padding";
public String encrypt(String value, String key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), ALGORITHM);
Cipher cipher = Cipher.getInstance(MODE);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(key.getBytes()));
byte[] values = cipher.doFinal(value.getBytes());
return Base64.encodeToString(values, Base64.URL_SAFE);
}
public String decrypt(String value, String key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
byte[] values = Base64.decode(value, Base64.DEFAULT);
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), ALGORITHM);
Cipher cipher = Cipher.getInstance(MODE);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(key.getBytes()));
return new String(cipher.doFinal(values));
}
The encrypting code works perfectly fine but when I'm trying to decrypt the encrypted text it returns a bad base64 error.
What I tried to do before:
I already tried to change Base64.DEFAULT to Base64.URL_SAFE but it gave me the same error.
Also, I tried to replace "/" and "+" with "_" and "-" and it doesn't work either.
Heres the value I'm encrypted and trying to decrypt:
Ssg2w+dv7es7/wWAeAcoAOSVnYKsoLlefbmS8tYr+jc=
Thanks for helping...

Fail to decrypt Input length must be multiple of 16 when decrypting with padded cipher

I got an error Input length must be multiple of 16 when decrypting with padded cipher when trying to decrypt my encrypted message.
What I encrypt is this:
{
"guid": "d123-231s-2314w123-21312-2312312",
"userid": "000123",
"channel": "TESTINGCHANNELTEST"
}
but when I decrypt it I got that error. But when I decrypt this message
{
"guid": "00",
"userid": "00",
"channel": "TEST"
}
It works.
What make this issue?
Heres my code to encrypt and decrypt:
public class EncryptDecryptModel {
private static final String key = "aesEncryptionKey";
private static final String initVector = "encryptionIntVec";
public static String encrypt(String value) {
try {
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(value.getBytes());
return Base64.encodeBase64String(encrypted);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static String decrypt(String encrypted) {
try {
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));
//original = Base64.decodeBase64(encrypted);
return new String(original);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
This is to encrypt:
#PostMapping("/getEncrypt")
public String getEncrypt(#RequestBody OpenMediaModel openMediaModel) throws UnsupportedEncodingException, InvalidAlgorithmParameterException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException {
EncryptDecryptModel encryptDecryptModel=new EncryptDecryptModel();
MessageDigest digest = MessageDigest.getInstance("SHA-256");
String message = openMediaModel.getGuid() + "|" + openMediaModel.getCif()
+ "|" + openMediaModel.getChannel();
byte[] encodedhash = digest.digest(
message.getBytes(StandardCharsets.UTF_8));
message = message + "|" + new String(encodedhash);
return encryptDecryptModel.encrypt(message);
}
And this is how I decrypt my message:
#GetMapping("/getDecrypt")
public String getDecrypt(#RequestParam String encrypt) throws NoSuchPaddingException, UnsupportedEncodingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidKeyException {
EncryptDecryptModel encryptDecryptModel=new EncryptDecryptModel();
String plainMessage = encryptDecryptModel.decrypt(encrypt);
String[] splitMessage = plainMessage.split("\\|");
MessageDigest digest = MessageDigest.getInstance("SHA-256");
String message = splitMessage[0] + "|" + splitMessage[1]
+ "|" + splitMessage[2];
//byte[] encodedhash = digest.digest(
// message.getBytes(StandardCharsets.UTF_8));
//return new String(encodedhash).equals(splitMessage[3]);
return splitMessage[0]+"-"+splitMessage[1]+"-"+splitMessage[2];
}
The Issue is when I put long json format like the first one, I got exception:
javax.crypto.IllegalBlockSizeException: Input length must be multiple
of 16 when decrypting with padded cipher
Sorry this is my first time do this encrypt. So got no clue when I decrypt long message. since It work well when I do short message. and I tried use that decodeBase64 but no value
Need help with this.
Thanks in advance.

How to decrypt EncryptedAssertion manually

I want to decrypt the EncryptedAssertion. I tried with OpenSaml Decrypter but its not working for me.I am getting Failed to decrypt EncryptedData
I have already ask that question - EncryptedAssertion Decryption failing
While I am waiting for any solution I am trying to decrypt it manually. Its a Hybrid encryption
I tried below code
CipherValue cv = encryptedAssertion.getEncryptedData().getKeyInfo().getEncryptedKeys().get(0).getCipherData().getCipherValue();
String cvalue = cv.getValue();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, getPrivateKey());
String decryptedValue = new String(cipher.doFinal(DatatypeConverter.parseBase64Binary(cvalue)));
I am not sure if I am on the right path, but above decryptedValue is the decryption key for my Encrypted Data.This decryptedValue is not in readable format. Not sure what to do next.
getPrivateKey method
public PrivateKey getPrivateKey(){
Key key = null;
PrivateKey privateKey = null;
try {
KeyStore ks = KeyStore.getInstance("pkcs12", "SunJSSE");
ks.load(new FileInputStream("prvkey.pfx"),"".toCharArray());
Enumeration<String> aliases = ks.aliases();
while(aliases.hasMoreElements()){
String alias = aliases.nextElement();
key = ks.getKey(alias, "".toCharArray());
privateKey = (PrivateKey)key;
}
} catch (Exception e) {
e.printStackTrace();
}
}
Based on the suggestion I coded like below. Not sure if I am doing it correct also I am getting errors
`CipherValue cv = encryptedAssertion.getEncryptedData().getKeyInfo().getEncryptedKeys().get(0).getCipherData().getCipherValue();
String cvalue = cv.getValue();
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.UNWRAP_MODE, getPrivateKey());
Key decryptionKey = cipher.unwrap(DatatypeConverter.parseBase64Binary(cvalue), "RSA/ECB/PKCS1Padding", Cipher.SECRET_KEY);
CipherValue cdata = encryptedAssertion.getEncryptedData().getCipherData().getCipherValue();
String cdataValue = cdata.getValue();
byte[] iv = new byte[256 / 16];
IvParameterSpec ivParamSpec = new IvParameterSpec(iv);
Cipher cipher2 = Cipher.getInstance("AES/CBC/PKCS5PADDING");
SecretKeySpec spec = new SecretKeySpec(decryptionKey.getEncoded(), "AES");
cipher2.init(Cipher.DECRYPT_MODE, spec, ivParamSpec );
String decryptedValue = new String(cipher2.doFinal(DatatypeConverter.parseBase64Binary(cdataValue)));`
Error -
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.CipherCore.doFinal(CipherCore.java:824)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
at javax.crypto.Cipher.doFinal(Cipher.java:2121)
UPDATE ::
hope I am doing it correctly based on the comments.
byte[] iv = new byte[256/16];
iv = Arrays.copyOfRange(DatatypeConverter.parseBase64Binary(cdataValue), 0, 16);
byte[] cipherBlock = Arrays.copyOfRange(DatatypeConverter.parseBase64Binary(cdataValue), 16, DatatypeConverter.parseBase64Binary(cdataValue).length);
IvParameterSpec ivParamSpec = new IvParameterSpec(iv);
Cipher cipher2 = Cipher.getInstance("AES/CBC/PKCS5PADDING");
SecretKeySpec spec = new SecretKeySpec(decryptionKey.getEncoded(), "AES");
cipher2.init(Cipher.DECRYPT_MODE, spec, ivParamSpec );
String decryptedValue = new String(cipher2.doFinal(cipherBlock)); // Same error - Given final block not properly padded
I won't provide you a complete answer but I hope to get you on the right track
You should not just simply decrypt the calue with the private key.
First decrypt the KeyInfo value (unwrap the aes key) using RSA/ECB/PKCS1Padding (according to the provided saml snippet)
It should give you a 256 bit (32 bytes) random key used to encrypt data itself
then use the AES key to decrypt the data . Please note that first bytes (128 bit / 16 bytes, aes block size) is used as IV.
further reading
https://www.w3.org/TR/2002/REC-xmlenc-core-20021210/Overview.html#sec-Processing-Encryption
https://gusto77.wordpress.com/2017/10/30/encryption-reference-project/
public static byte[] decrypt(byte[] cryptoBytes, byte[] aesSymKey)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
// https://github.com/onelogin/java-saml/issues/23
String cipherMethod = "AES/CBC/ISO10126Padding"; // This should be derived from Cryptic Saml
AlgorithmParameterSpec iv = new IvParameterSpec(cryptoBytes, 0, 16);
// Strip off the the first 16 bytes because those are the IV
byte[] cipherBlock = Arrays.copyOfRange(cryptoBytes,16, cryptoBytes.length);
// Create a secret key based on symKey
SecretKeySpec secretSauce = new SecretKeySpec(aesSymKey, "AES");
// Now we have all the ingredients to decrypt
Cipher cipher = Cipher.getInstance(cipherMethod);
cipher.init(Cipher.DECRYPT_MODE, secretSauce, iv);
// Do the decryption
byte[] decrypedBytes = cipher.doFinal(cipherBlock);
return decrypedBytes;
}
ISO10126Padding should work....

Java AES encryption/decryption procedure and usage of Initialization Vector

I want to learn the basics of AES encryption so I started to make a very simple Java program. The program loads a text file in to a String and asks for a key from the user. The program then uses AES to encrypt the text creating a new text file with the encrypted text. The program prints the Initialization Vector (IV) to the user.
The program also has the decryption function. The user specifies the encrypted text file along with the Initialization Vector and the key to decrypt it back to the original text in a new text file.
However I think I'm doing something wrong. Is it normal procedure in AES encryption that the user needs to have both key and IV to decrypt the file? I have browsed through the internet and almost in every example, the encrypted data can be decrypted by the user specifying only the key but in my case the user needs to have both the key and the IV. The program is working fine but I think it isn't efficient.
So should I use a constant, known IV which is used in all the encryptions and decryptions or what? Also some tutorials are using "salt", what is it and should I use it?
Here are my encrypt and decrypt methods:
public String encrypt(String stringToEncrypt, String userKey)
throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
// User gives string key which is formatted to 16 byte and to a secret
// key
byte[] key = userKey.getBytes();
MessageDigest sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 16);
SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
// Cipher initialization
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
// Encryption and encoding
String encryptedData = new BASE64Encoder().encode(cipher
.doFinal(stringToEncrypt.getBytes()));
// IV is printed to user
System.out.println("\nENCRYPTION IV: \n"
+ new BASE64Encoder().encode(cipher.getIV()) + "\n");
// Function returns encrypted string which can be writed to text file
return encryptedData;
}
public String decrypt(String stringToDecrypt, String userKey, String userIv)
throws NoSuchAlgorithmException, IOException,
NoSuchPaddingException, InvalidKeyException,
InvalidAlgorithmParameterException, IllegalBlockSizeException,
BadPaddingException {
// User gives the same string key which was used for encryption
byte[] key = userKey.getBytes();
MessageDigest sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 16);
SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
// Decode string iv to byte
byte[] iv = new BASE64Decoder().decodeBuffer(userIv);
// Cipher initialization
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv));
// Decryption and decoding
String decryptedData = new String(cipher.doFinal(new BASE64Decoder()
.decodeBuffer(stringToDecrypt)));
// Function returns decrypted string which can be writed to text file
return decryptedData;
}
UPDATE
I updated my code now to use "PBKDF2WithHmacSHA256" algorithm with salt and etc. I also combined the Initialization Vector (IV) byte array to the cipher text byte array as prefix so I can split them in decrypt method and get the IV there (That's working fine).
However there's now an issue with the key, because I'm generating new encrypted key also in decryption method which of course is a wrong key for encrypted data. I want to be able to close the program so I can't store the key as a class variable. It's very hard to explain the issue but I hope you understand the problem...
public static byte[] getEncryptedPassword(String password, byte[] salt,
int iterations, int derivedKeyLength)
throws NoSuchAlgorithmException, InvalidKeySpecException {
KeySpec mKeySpec = new PBEKeySpec(password.toCharArray(), salt,
iterations, derivedKeyLength);
SecretKeyFactory mSecretKeyFactory = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA256");
return mSecretKeyFactory.generateSecret(mKeySpec).getEncoded();
}
public String encrypt(String dataToEncrypt, String key) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidParameterSpecException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException {
byte[] mEncryptedPassword = getEncryptedPassword(key, generateSalt(),
16384, 128);
SecretKeySpec mSecretKeySpec = new SecretKeySpec(mEncryptedPassword, "AES");
Cipher mCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
mCipher.init(Cipher.ENCRYPT_MODE, mSecretKeySpec);
byte[] ivBytes = mCipher.getIV();
byte[] encryptedTextBytes = mCipher.doFinal(dataToEncrypt.getBytes());
byte[] combined = new byte[ivBytes.length+encryptedTextBytes.length];
System.arraycopy(ivBytes, 0, combined, 0, ivBytes.length);
System.arraycopy(encryptedTextBytes, 0, combined, ivBytes.length, encryptedTextBytes.length);
return Base64.getEncoder().encodeToString(combined);
}
public String decrypt(String dataToDecrypt, String key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
byte[] encryptedCombinedBytes = Base64.getDecoder().decode(dataToDecrypt);
byte[] mEncryptedPassword = getEncryptedPassword(key, generateSalt(),
16384, 128);
byte[] ivbytes = Arrays.copyOfRange(encryptedCombinedBytes,0,16);
SecretKeySpec mSecretKeySpec = new SecretKeySpec(mEncryptedPassword, "AES");
Cipher mCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
mCipher.init(Cipher.DECRYPT_MODE, mSecretKeySpec, new IvParameterSpec(ivbytes));
byte[] encryptedTextBytes = Arrays.copyOfRange(encryptedCombinedBytes, 16, encryptedCombinedBytes.length);
System.out.println(encryptedTextBytes.length);
byte[] decryptedTextBytes = mCipher.doFinal(encryptedTextBytes);
return Base64.getEncoder().encodeToString(decryptedTextBytes);
}
public byte[] generateSalt() {
SecureRandom random = new SecureRandom();
byte saltBytes[] = new byte[16];
random.nextBytes(saltBytes);
return saltBytes;
}}
I hope somebody knows how to make this better. Thanks!
Just save the IV in the file before the encrypted data.
You should never use the same IV more than once (it's ok-ish, if you roll a new IV every time, and it just so happens that you roll the same twice, so you don't have to store and check that). Using the same IV many times poses a great security risk, as encrypting the same content twice reveals that it's - in fact - the same content.
Storing IV alongside the encrypted data is a common, and secure procedure, as it's role is to introduce "randomness" to the encryption scheme, and it shouldn't be secret, just securely (and in some schemes randomly) generated.

Java File Encryption

I'm trying to write a simple program to encrypt and decrypt files using the AES algortihm. I haven't problems with encryption, but decryption..
public static void main(String[] args) throws NoSuchAlgorithmException, FileNotFoundException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
// Инициализация секретных ключей
KeyGenerator keyGenS = KeyGenerator.getInstance("AES");
keyGenS.init(128);
SecretKey sKey1 = keyGenS.generateKey();
SecretKey sKey2 = keyGenS.generateKey();
// Перевод секретных ключей в строку и запись в файл
String key1 = SecretKeyToString(sKey1);
String key2 = SecretKeyToString(sKey2);
spreader.write(fileName1, key1);
spreader.write(fileName2, key2);
spreader.write(fileNameS1, key1);
spreader.write(fileNameS2, key2);
// Чтение секретных ключей из файла и перевод обратно в тип SecretKey
key1 = spreader.read(fileName1);
System.out.println("Секретный ключ 1го пользователя: " +key1);
SecretKey seansKey1=getKeyInstance(key1);
key2 = spreader.read(fileName2);
System.out.println("Секретный ключ 2го пользователя: " +key2);
SecretKey seansKey2=getKeyInstance(key2);
//инициализация и зашифрование сеансового ключа с помощью секретных
Cipher aesCipher = Cipher.getInstance("AES");
aesCipher.init(Cipher.ENCRYPT_MODE,seansKey1);
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
SecretKey secretKey = keyGen.generateKey();
String stringsecretKey = SecretKeyToString(secretKey);
byte[] byteKey = stringsecretKey.getBytes();
byte[] byteCipherKey1 = aesCipher.doFinal(byteKey);
String encryptedKey = new BASE64Encoder().encode(byteCipherKey1);
System.out.println("Зашифрованный сеансовый ключ с помощью секретного ключа 1: " +encryptedKey);
aesCipher = Cipher.getInstance("AES");
aesCipher.init(Cipher.ENCRYPT_MODE,SeansKey2);
byteKey = etringsecretKey.getBytes();
byte[] byteCipherKey2 = aesCipher.doFinal(byteKey);
encryptedKey = new BASE64Encoder().encode(byteCipherKey2);
System.out.println("Зашифрованный сеансовый ключ с помощью секретного ключа 2: " +encryptedKey);
spreader.write(fileNameEK2, encryptedKey);
//Чтение данных из файла
String text =spreader.read(fileName);
System.out.println(text);
// Зашифрование данных
aesCipher.init(Cipher.ENCRYPT_MODE,secretKey); // константная переменная
byte[] byteText = text.getBytes();
byte[] byteCipherText = aesCipher.doFinal(byteText);
encryptedText = new BASE64Encoder().encode(byteCipherText);
System.out.println("Зашифрованный текст: " +encryptedText);
spreader.write(fileNameOK, encryptedText);
}
Here's the decryption part:
public static void main(String[] args) throws NoSuchAlgorithmException, FileNotFoundException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, UnsupportedEncodingException {
String encryptedText = user.read(fileNameOK);
String key1 = user.read(fileName1);
String key2 = user.read(fileName2);
String encryptedSeanceKey1 = user.read(fileNameEK1);
String encryptedSeanceKey2 = user.read(fileNameEK2);
SecretKey secretKey1=getKeyInstance(key1);
SecretKey secretKey2=getKeyInstance(key2);
Cipher aesCipher = Cipher.getInstance("AES");
aesCipher.init(Cipher.DECRYPT_MODE,secretKey1,aesCipher.getParameters());
//byte[] byteKey = encryptedSeanceKey1.getBytes();
byte[] byteDecryptedKey = aesCipher.doFinal(encryptedSeanceKey1.getBytes());
String decryptedKey1 = new String(byteDecryptedKey);
System.out.println("Расшифрованный сеансовый ключ с помощью секретного ключа 1: " +decryptedKey1);
aesCipher.init(Cipher.DECRYPT_MODE,secretKey2,aesCipher.getParameters());
byte[] byteKey2 = encryptedSeanceKey2.getBytes();
byteDecryptedKey = aesCipher.doFinal(byteKey2);
String decryptedKey2 = new String(byteDecryptedKey);
System.out.println("Расшифрованный сеансовый ключ с помощью секретного ключа 2: " +decryptedKey2);
// Расшифрование данных
aesCipher.init(Cipher.DECRYPT_MODE,getKeyInstance(decryptedKey1),aesCipher.getParameters());
byte[] byteText = encryptedText.getBytes();
byte[] byteDecryptedText = aesCipher.doFinal(byteText);
decryptedText = new String(byteDecryptedText);
System.out.println(" Расшифрованный текст " +decryptedText);
}
}
Now the problem is the decryption part is: Input length must be multiple of 16 when decrypting with padded cipher
I know that a mistake that I incorrectly keep a session key and bytes are lost. But how I can correctly do it?
There is a little bit of confusion in your code, maybe because some method you called are missing, or maybe because you are using your keys to encrypt...your keys(!!!)
Let's try to encrypt and decrypt the easy way, removing all the stuff that is not strictly needed in your code (like encode your key and save it to a file, and then restore the key without decoding it, etc..).
Let's take a look at the following simplified code based on your:
KeyGenerator keyGenS = KeyGenerator.getInstance("AES");
keyGenS.init(128);
SecretKey sKey1 = keyGenS.generateKey();
Cipher aesCipher = Cipher.getInstance("AES");
aesCipher.init(Cipher.ENCRYPT_MODE,sKey1);
byte[] byteText = "Insert here whatever you want to crypt".getBytes();
byte[] byteCipherText = aesCipher.doFinal(byteText);
We have generated our key with KeyGenerator, and then we have initialized our Cipher instance with that key. At this point we simply call doFinal() passing the plainText we want to encrypt.
That's all for the encryption part. Of course you can save your keys and byteCipherText to a file if you want, but all the other staff is (at least) useless.
The decryption part is easy as the encryption. The logic is the same.
If you saved your key on a file, just read it into a byte[], and use it for initialize your cipher instance. Something like this:
aesCipher.init(Cipher.DECRYPT_MODE, sKey1);
byte[] plainText = aesCipher.doFinal(byteCipherText);
If you put all the above code into a main() and run it, you should have into plainText the same text as in byteText.
You can verify it with a
System.out.println(new String(plainText));
Try to start from here, then add all other things you may need.
Hope this helps.
Regards

Categories