Decrypted String Always Returning Null

Decrypt method returning null

Aside from everything else, the most fundamental problem you've got here is that you're converting binary data to a string just using the platform default encoding, as if it's actually just text. It's not - it's binary data.

If you want one line of text per encrypted input, that's fine - but you need to convert the binary data to text as base64 or something similar. Never, ever, ever treat arbitrary binary data (encrypted data, compressed data, image data, music data... basically anything other than text) as if it's just encoded text. Even when you do have encoded text, specify the encoding explicitly.

Fix that - and stop using BufferedReader.ready(), preferring to call readLine() and terminate when it returns null - and you'll be in a better position. Fix the exception handling too, of course.

See my blog post about reversible transformations for more information about diagnosing this sort of thing, and Marc Gravell's post about IO for more about IO bugs.

C# - Problem with AES Decryption - always get null

You don't show how you use your Encryptor class, so your question doesn't quite include a Minimal, Complete, and Verifiable example. I was able to reproduce the problem with the following test harness:

public static void Test()
{
var key = "my key";
var plainText = "hello";

var encryptor = new Encryptor();

encryptor.setDecryptedText(plainText);
encryptor.setKey(key);

var encrypted = encryptor.getEncrypted();

Console.WriteLine(encrypted);

var deecryptor = new Encryptor();

deecryptor.setEncryptedText(encrypted);
deecryptor.setKey(key);

var decrypted = deecryptor.getDecrypted();

Console.WriteLine(decrypted);

Assert.IsTrue(plainText == decrypted);
}

Demo fiddle #1 here.

Given that, your code has 2 problems, both of which are actually in encryption rather than decryption.

Firstly, in Encrypt(string plainText, byte[] Key, byte[] IV), you are writing to the StreamWriter sw, then flushing the CryptoStream and returning the MemoryStream contents -- but you never flush or dispose sw, so its buffered contents are never forwarded to the underlying stream(s).

To fix this, your code should looks something like:

using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(Encoding.UTF8.GetBytes(plainText));
}
}
encrypted = ms.ToArray();
}

Now getDecrypted() no longer returns a null result -- but instead returns a wrong result of "System.Byte[]", as shown in demo fiddle #2 here.

Secondly, again in Encrypt(...), you are effectively encoding your plainText twice at this line:

sw.Write(Encoding.UTF8.GetBytes(plainText));

Encoding.UTF8.GetBytes(plainText) converts the plain text to a byte array, but the StreamWriter is also intended to do this job, converting strings to bytes and passing them to the underlying stream. So, since you are not passing a string to Write(), the overload that gets called is StreamWriter.Write(Object):

Writes the text representation of an object to the text string or stream by calling the ToString() method on that object.

Thus what actually gets encrypted is the ToString() value of a byte array, which is "System.Byte[]".

To fix this, simply remove the call to Encoding.UTF8.GetBytes(plainText) and write the string directly. Thus your Encrypt() method should now look like:

static String Encrypt(string plainText, byte[] Key, byte[] IV)
{
string encrypted;
using (var aes = new RijndaelManaged())
{
aes.Mode = CipherMode.CBC;
aes.BlockSize = 128;
aes.KeySize = 256;
ICryptoTransform encryptor = aes.CreateEncryptor(Key, IV);
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write, true))
{
using (var sw = new StreamWriter(cs))
{
sw.Write(plainText);
}
}
// Calling GetBuffer() avoids the extra allocation of ToArray().
encrypted = Convert.ToBase64String(ms.GetBuffer(), 0, checked((int)ms.Length));
}
aes.Clear();
}

return encrypted;
}

Demo fiddle #3 here that now passes successfully.

Disclaimer: this answer does not attempt to to review your code for security best practices such as secure setup of salt and IV.

jsencrypt returns null decrypting string from encrypt function

You need to call the functions setPublicKey and setPrivateKey rather than assigning them.

Since you weren't actually setting the keys, the previous output would have been encoded with a different key, hence why it won't decode.

The previous example of an encrypted string 'EutZlbeFV2RTG8mk6xUMi/ceN1h...' you used also won't decode, since it was encoded using another key (which has probably been lost.)

But if you copy and paste from now on, the text will decode.

Note that you only need to set the private key, since the private key contains the public key parameters

const crypt = new JSEncrypt();

// Set private key
crypt.setPrivateKey(`-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKcvhICRdeZ65vYN
xyBNPi/0RCu+S+o9A/NE854gvnbm1B3u+DUGWDHGehLigOfQbcmXOojrL9UhpnLp
CsijezlHYD0iLKY+R5U6KHhXlB41IA7y2ZRsRfi4QVZAPI5sx7IXjhHt9SjJQJwL
9Z0p7PBwmWCrp1cgUk7ITPAnHQw9AgMBAAECgYEAl4kAZrBx1wiLE3cFiAe7WCfl
Kmj/0j6ft/5FeoxfVtJ+bOtPWnB3vBYUS8213WgUOuayDaxu3JX1kq4cMiPL6XWC
gznYdRDrO/92E5OyOjmrAGzItDv/SIoBGv68f/kxYC989H+yd7aCqF8SfRlR0ESi
PnLLSYZfRsB4oLeSpkECQQDZdMLOZ3uiRwBvPV79mqfmME2OpB5VssAS9GO+giF3
c8jibpre2wV/xWZ4/ACeXmFRgejVp09JEvF2OARhgSyVAkEAxNGxzJH22E0ZT3kq
W7L7o8mkCQVjLK99dMaagUg+VpKk+4Y02hBStLP4xnIHt7NfpQ7r+cebk3ZeH5Ep
hO7PCQJBALcKhpPxHWuKcn4wXY4BKYUkcZQ452Phk7YgyvjoVr1S0+xth6VBHU7g
3ZHHJcoozagrPs7hB2cOL/v/yQg+EEUCQH5Ila5OkXWjsnO9qKIBq1giDvAC1ulb
CEIfFA+TjPv7R4RjThIEmyx6tUqO68jAfMPpWRuBKZ9qOWZDu8IhgBECQCZTubwP
zZ+9Kntj9BcoRjYYMeWK8voPzS4n1S8PK3249e7GdfX/Z7OcsvV9gYJ7CZ6W41fo
wa3MnlkEivo3mrA=
-----END PRIVATE KEY-----`);

const text = "some data";
const enc = crypt.encrypt(text);
const dec = crypt.decrypt(enc);
console.log('enc:', enc);
const temp = 'T9tsyIGc+fFea7GWKHiJLOVbZf3vqiVEy/qBK37hxrGlsEQWh2HgD5+76XVqkmz6yU6w77CMX3wsRtH3KeD2NY4wxsb18JwcO4yJcaFL+ZwJ7WS8PuGY4YI5UxW3v2lwkwZ2x8GO/lE25pPJ4+f5bdeM4Yk5KWt6hV3z/yXCwvc=';
const dec2 = crypt.decrypt(temp);
console.log('dec2:', dec2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsencrypt/2.3.1/jsencrypt.min.js" integrity="sha512-zDvrqenA0eFJZCxBsryzUZcvihvNlEXbteMv62yRxdhR4s7K1aaz+LjsRyfk6M+YJLyAJEuuquIAI8I8GgLC8A==" crossorigin="anonymous"></script>

When encoding the password, always return null value

AES only supports key sizes of 16, 24 or 32 bytes. Your key length is 14, add 2 more digits to your key and it will work.

private static final Long ENCRYPTION_KEY = 2919021090891712L; //16 bytes

AES decryption is always null

Well, i found the error. It was in the encryption method. encMessage was null before the encryption process begins. String encMessage = message did the trick. So the encryption method is:

 public static String encryptMessage(String message, String salt) {
String encMessage = message;
byte[] encVal = null;
String messageWithSalt = null;
try {
Key key = generateKey();

Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.ENCRYPT_MODE, key);

for (int i = 0; i < ITERATIONS; i++) {
messageWithSalt = salt + encMessage;
encVal = c.doFinal(messageWithSalt.getBytes());
byte[] encryptedValue = new Base64().encode(encVal);
encMessage = new String(encryptedValue);
}

} catch (Exception e) {
e.printStackTrace();

}
return encMessage;
}

Returning null password when read decrypted password from decryppwd.sh file

I was able to solve my issue by reading only 1st line of the BufferedReader.



Related Topics



Leave a reply



Submit