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
A Concise Way to Not Execute a Loop Now That C-Style for Loops Are Going to Be Removed from Swift 3
Issue with Returning a Directory Enumerator from Nsfilemanager Using Enumeratoraturl in Swift
Pass Type to Generic Function and Compare
Why Is Swift Counting This Grapheme Cluster as Two Characters Instead of One
Swift: Using Member Constant as Default Value for Function Parameter
How to Use The Snapchat Sdk (Snapkit) with Swiftui
In Swift 5, What Is a Way to Compare Pointers to Two Closures
Detecting End of The Playback in Avaudioplayer
Swift Difference Between Double and Float64
Realm: Predicate Returning Lazyfiltercollection - How to Convert to Results<T>
Include Dictionary or Array Value in Swift String with Backslash Notation
Bundle.Main.Path(Forresource... Always Returns Nil When Looking for Xml File
Finding The First Non-Repeating Character in a String Using Swift
Navigationlink Doesn't Work with New .Searchable Modifier on Swiftui 3.0