Decrypt SHA encrypted string [duplicate] - java

This question already has answers here:
How to decrypt a SHA-256 encrypted string?
(4 answers)
Closed 9 years ago.
I have encrypted a string using the above code.
public String encrypt(String generatedKey)
{
try {
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(generatedKey.getBytes("UTF-8"));
byte digest[] = md.digest();
return (new BASE64Encoder()).encode(digest);
}
catch (Exception e) {
return null;
}
}
Similarly i need a code to decrypt the above generated code. How can i do this?

SHA is a digest algorithm, not an encryption algorithm. Digest values are not decryptable. That's why they are secure. Two different inputs may give same digest values. But it is a very little possibility. For sha256 it is 1/(2^256).
Output of digest algorithms have constant length. For SHA256 it is always 256 bit, regardless of your input length, 1 bit or 100 Gbs. If we could decrypt 256 bit digest value and have the original 1Gb input back, we would never need compression algorithms :)

Message digests produce a small "fingerprint" of a larger set of data. It's a one way procedure.
What you probably is looking for is encryption.
Key key = new SecretKeySpec(secret.getBytes(), ALGORITHM);
// Encrypt
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedData = cipher.doFinal(plainText);
// Decrypt
cipher.init(Cipher.DECRYPT_MODE, key)
byte[] decryptedData = cipher.doFinal(encryptedData);
Where ALGORITHM can be one of
http://docs.oracle.com/javase/6/docs/technotes/guides/security/StandardNames.html#Cipher

I am pretty sure that we cannot decode a SHA encrypted string directly.
See this for a clear explanation: How to decrypt SHA-256 encrypted String?

Related

JAVA - AES Decryption - Input length must be multiple of 16 when decrypting with padded cipher

I am trying to decrypt the ResponseText variable which i get from an API. I am getting the following error.
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be
multiple of 16 when decrypting with padded cipher
Below is my code snippet for decrypting the response. The Decrytpt method is throwing the error.
public static String decrypt(String encryptedText) throws Exception
{
Key key = generateKey();
Cipher chiper = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivspec = new IvParameterSpec(iv);
chiper.init(Cipher.DECRYPT_MODE, key, ivspec);
byte[] encVal = chiper.doFinal(encryptedText.getBytes("UTF-8"));
Base64.Encoder base64Encoder = Base64.getEncoder();
String decryptedValue = base64Encoder.encodeToString(encVal);
String decryptedString= new String("");
return decryptedString;
}
I have not posted the actual encrypted value here as the length of the encrypted value is too high. I am new to Java. Thanks in advance.
You should probably base 64 decode the ciphertext, decrypt the binary ciphertext and then decode the resulting plaintext to UTF-8.
You haven't correctly reversed the encryption routine (encode UTF-8, encrypt, encode base64), in other words.
There is a generateKey() for the decryption; unless it returns a static value (and doesn't generate one, as the method name implies) decryption will likely fail. So either the name is wrong, or the decryption.
The IV doesn't seem to be included with the ciphertext either, which will mean that that's the next problem to deal with.
Finally, you will want to know how to handle exceptions for encryption / decryption routines.

Openssl (shell script) equivalent of java decryption code

Need help with openssl, What would be the openssl equivalent of the below java method?
private static String decryptString(String value, String myKey) {
MessageDigest sha = null;
SecretKeySpec secretKey = null;
try {
byte[] key = myKey.getBytes("UTF-8");
sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 16); // use only first 128 bit
secretKey = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return (new String(cipher.doFinal(Base64.decodeBase64(value))));
} catch (Exception e) {
System.out.println("Error while decrypting: " + e.toString());
}
return null;
}
The function is digesting a string (myKey) using SHA-1 and then using the first 16 bytes of the resulting digest as the key for an AES128-ECB decryption operation. Before decryption, the ciphertext is first base64 decoded.
To digest a string using SHA-1 use the code here:
https://wiki.openssl.org/index.php/EVP_Message_Digests
That code actually uses SHA-256. To make it do SHA-1 instead replace the instance of EVP_sha256() with EVP_sha1(). The first 16 bytes of the result is your "key".
Next the input "value" is base64 decoded. There is some sample code to do that with OpenSSL here:
http://www.ioncannon.net/programming/122/howto-base64-decode-with-cc-and-openssl/
Finally, to do the AES-ECB decryption operation use the code here:
https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption#Decrypting_the_Message
That code is using AES256-CBC. To make it do AES128-ECB instead replace the instance of EVP_aes_256_cbc() with EVP_aes_128_ecb(). The key argument is as you calculated above. The iv argument is just NULL for ECB. The ciphertext is the base64 decoded data that you calculated above. Note that the "PKCS5PADDING" part of the Java code is the default in OpenSSL anyway, so nothing special needs to be done for that.
The plaintext that has been output from the decryption operation is the return value from your Java function.

Incorrect Key Length for Padded Encryption [duplicate]

This question already has an answer here:
bytes in 'str = new String(bytes, "UTF8") ' and 'bytes = str.getBytes("UTF8")' not the same value
(1 answer)
Closed 6 years ago.
I have been having a problem with doing padded encryption. I think I have isolated the issue to this function:
static String AESEncryptStringWithPassword(String s, String p) throws...{
//function to create key from string password
SecretKey secret = deriveAESKey(p);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
iv = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] ciphertext = cipher.doFinal(s.getBytes(Charset.forName("UTF-8")));
String str = Base64.getEncoder().encodeToString(ciphertext);
return str;
}
Down the line when I go to decrypt I will get an error like so: Input length must be multiple of 16 when decrypting with padded cipher.
I have checked and this method is the origin of the bad length string. No further methods corrupt it. I'm not sure exactly what I'm doing wrong. I have based my code on the question here: Java 256-bit AES Password-Based Encryption
EDIT: I have changed the encoding slightly to use String(byte[], charset) instead. However now with defaultcharset I have an appropriate string length and with utf-8 I do not.
The conversion between byte[] and String throughout the program seemed to be the problem. Kept it as byte[] as much as possible and then it worked.
So, lesson learned: Careful converting between byte[] and String.

Java simple helloworld AES encryption decryption [duplicate]

This question already has answers here:
UTF-8 byte[] to String
(11 answers)
Closed 8 years ago.
I got a code snippet from another SO question and modified it a bit but I can't seem to get it to work. Can anyone figure out why? it's currently printing [B#405e70bc or similar values. All I'm trying to do is store a password in an encrypted form just for the sole purpose of keeping it away from curious eyes, is there a better way to do that?
String secret = "1234567812345678";
Key key = new SecretKeySpec(secret.getBytes(), "AES");
// Encrypt
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedData = cipher.doFinal("helloworld".getBytes());
// Decrypt
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedData = cipher.doFinal(encryptedData);
System.out.println(decryptedData.toString());
There is nothing wrong with your encryption / decryption logic. The problem is with you calling .toString() on a byte [].
Use this output statement instead:
System.out.println(new String(decryptedData));
Thanks Alexander.
This worked
String secret = "1234567812345678";
Key key = new SecretKeySpec(secret.getBytes(), "AES");
// Encrypt
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedData = cipher.doFinal("helloworld".getBytes());
// Decrypt
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedData = cipher.doFinal(encryptedData);
System.out.println(new String(decryptedData, "UTF-8"));
Please don't use this for anything critical. The standard Java AES code makes use of a fixed-length block cipher which can result in identical encrypted byte data. The upshot is a gradual leakage of plaintext information.
You should look into Cipher Block Chaining and Initialisation Vectors if you want your code to be more robust. http://www.javamex.com/tutorials/cryptography/block_modes.shtml
It may be overkill for your needs, but just thought i'd mention it.

Java public private key decryption issue

I am trying to encrypt and decrypt a message as mentioned in the below code. Basically I want to encrypt a message with a public key and convert that encrypted message from byte array to String. And decrypt this string into original text. Here are the both methods. Here encryption works fine but decryption fails (error is "Data must start with zero"). I think this is causing because I convert encrypted byte array into String.
How do I solve this? (I want to have encrypted byte array as string and use it for decryption) Is there any other approach (with public and private keys)
public static String getEncryptedMessage(String publicKeyFilePath,
String plainMessage) {
byte[] encryptedBytes;
try {
Cipher cipher = Cipher.getInstance("RSA");
byte[] publicKeyContentsAsByteArray = getBytesFromFile(publicKeyFilePath);
PublicKey publicKey = getPublicKey(publicKeyContentsAsByteArray);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
encryptedBytes = cipher.doFinal(plainMessage.getBytes());
return new String(encryptedBytes);
} catch (Throwable t) {
}
}
public static String getDecryptedMessage(
String privateKeyFilePath, String encryptedMessage)
{
byte[] decryptedMessage;
try {
Cipher cipher = Cipher.getInstance("RSA");
byte[] privateKeyContentsAsByteArray = getBytesFromFile(privateKeyFilePath);
PrivateKey privateKey = getPrivateKey(privateKeyContentsAsByteArray);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
decryptedMessage = cipher.doFinal(encryptedMessage.getBytes());
return new String(decryptedMessage);
} catch (Throwable t) {
}
If you look at this page (http://www.wikijava.org/wiki/Secret_Key_Cryptography_Tutorial) you will need to do base-64 encoding to turn the bytes into a string, then to decrypt it you would just decode it then decrypt.
Base-64 encoding uses the first 7 bits of a byte, to make something that is printable or emailable, for example.
UPDATE:
I made a mistake, there are 64 characters that it would be encoded in, again, in order to make it easier to use as something printable.
Why don't you treat the message as byte array from encryption to decryption? Why changing it to String in the middle? (I know it seems like a question, but it's actually an answer...)
Using RSA directly on unformatted data may leave your application vulnerable to an adaptive chosen ciphertext attack. For details please see Chapter 8, pages 288-289, of the Handbook of Applied Cryptography, a freely-available book from CRC Press. (It's well worth buying the bound edition, if you're really interested in cryptography -- you'll be stunned at the quality for the price.)
Because of this attack, most protocols that integrate RSA use RSA for encrypting randomly-generated session keys or signing hash functions with outputs that ought to be indistinguishable from random, OR using very carefully formatted messages that will fail to be correctly interpreted. (See Note 8.63 in HAC for details.)

Categories