Right I've a small problem. I'm using a Javascript library (jsencrypt) to encrypt a message in a browser. This message is then sent to the backend where it is decrypted using a Java library (bouncycastle). My problem is although I can encrypt and decrypt messages using both libraries they don't seem to want to work together. So when I encrypt my message in a browser and send it to the backend I end up getting garbled gibberish. Does anyone have any idea what's going on here?
JSENCRYPT
var text = "This is another msg!";
var pubkey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwyTZf5gRWJdEevtK7sJSz14lhs1Jw7+aFhGtr4cbDGxdiXH8J+BwuYmBc6QFMhRw7AeYcgkx9zPb3SICzr+oK17RMA6T66dH+GPXp75LFUmfONfk2JdSeO80mMODGctSuefWDvoQ24Cq0Bz+ysrhP7hRqvJso5a0GMNPwt8ErtWfz4HZjSsaaZ7gXga2h5dq1OTcGNfevkDN9CJtFW/0Wwb/F6cnXngVHE41rsN4POUB3IWcX2CrCGxSraa+xsT/P7AJ8HRJ4wcjl9G2K/rlHJ8ZXZKlIuWwEzx0/F0IjE+S93tLpDgt6YJxjWqYqjL2uuJAGmEU323+PWA3jFTC+QIDAQAB";
var encrypt = new JSEncrypt();
encrypt.setPublicKey(pubkey);
var ciphertext = encrypt.encrypt(text);
console.log("ciphertext : " + ciphertext);
var decrypt = new JSEncrypt();
decrypt.setPrivateKey($("#privkey").val());
var plaintext = decrypt.decrypt(ciphertext);
console.log("plaintext : " + plaintext);
BOUNCYCASTLE
String cipherText = "jQ/I+oyyIfG5ARIHZsa6MfxwHciCt+3p6l+bLh4NPinq2s8eDjbO9O8abhVt2xuBQQcPAIaqbiP3Y3vRFYLOD2O+inKWiL1SpSBxvUb0XlWMgLmOqWUL6w6sL2iEla3i5EbdlrkK0uLA7QOUc6/fGVyLVe8VL7Vv4BGlo/cxR2FN74HK4MtLFRNaLKejwD6WbCNQoz4sIMA/Ez8GRSVEMyeYVZoWELShvyIRCqVADboAeuEP5l+oFlzgQfW6HFdpPnX+9TnHrbezdWhXiuJiD1Mq4VTicsya50MNcXJuPDV7NINYZs72UCS8NTYvfVkFc2lO7EUlDvvJ7Ns4wWuuWQ==";
PemReader pemReader = new PemReader(new InputStreamReader(new FileInputStream("priv.pem")));
PemObject pemObject = null;
try
{
pemObject = pemReader.readPemObject();
} finally {
pemReader.close();
}
PrivateKey privateKey = EncryptionUtil.generatePrivateKey(pemObject.getContent());
byte[] plainText = EncryptionUtil.asymDecrypt(privateKey, cipherText.getBytes());
System.out.println(new String(plainText));
#EbbeM.Pedersen
You are properly getting different default padding modes. Keywords
like RSA-OAEP padding & PKCS#1 padding comes to mind.
This was indeed the issue. I changed the default padding in bouncycastle to PKCS#1 and it all works now.
Thanks a million.
Related
I have an asymmetric RSA key pair stored in two separate files. I want to generate a new symmetric key and encrypt it with public RSA key in my postbuild.js GULP script, so the user cannot access it. Then I want to send it to the C# server, where it would be decrypted and used.
I use the following JavaScript code in Node.js for encryption:
const generateAndEncryptKey = () => {
const symmetricKey = crypto.randomBytes(32);
const publicKey = fs.readFileSync("pubkey.pem", "utf8");
const encryptedSymmetricKey = crypto.publicEncrypt({
key: publicKey,
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
oaepHash: "sha256",
}, Buffer.from(symmetricKey)).toString("base64");
return encryptedSymmetricKey;
}
The above code somehow works and generates a base64 string that I later send to the server. I'm not sure if this is the correct way to do this.
But I'm unable to find a way to decrypt this string in C#. I tried to use the BouncyCastle library and the following code:
public string DecryptKey(string encryptedKey) {
var privateKey = #"-----BEGIN RSA PRIVATE KEY-----
...shortened...
-----END RSA PRIVATE KEY-----";
var bytesToDecrypt = Convert.FromBase64String(encryptedKey);
var decryptEngine = new Pkcs1Encoding(new RsaEngine());
using (var txtreader = new StringReader(privateKey)) {
AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)new PemReader(txtreader).ReadObject();
decryptEngine.Init(false, keyPair.Private);
}
var decrypted = Encoding.UTF8.GetString(decryptEngine.ProcessBlock(bytesToDecrypt, 0, bytesToDecrypt.Length));
return decrypted;
}
But the ProcessBlock method always throws an InvalidCipherTextException "unknown block type".
Can someone help me to find out what am I doing wrong or point me to another better way of achieving this?
Decryption with the C# code fails because in the NodeJS code OAEP/SHA256 is used as padding and in the C# code PKCS#1 v1.5 padding. For decryption to work, both paddings must be identical. The padding in the C# code can be adapted to that of the NodeJS code as follows:
var decryptEngine = new OaepEncoding(new RsaEngine(), new Sha256Digest());
Also, the decrypted key must not be UTF-8 decoded as this corrupts the data. Either it is returned as byte[], or if conversion to a string is desired, a suitable binary-to-text encoding such as Base64 or hex must be used.
With these changes decryption works in the C# code.
i need to decript my secret string generated from open_ssl php function with javascript.
I'm trying to decrypt string generated from php with cryptoJS
PHP FUNCTION
$encData = openssl_encrypt(utf8_encode($pure_string), 'DES-EDE3',$encryption_key , OPENSSL_RAW_DATA);
$session['chip'] = base64_encode($encData);
JAVASCRIPT FUNCTION
var keyHex = CryptoJS.enc.Utf8.parse(secretkey);
// direct decrypt ciphertext
var decrypted = CryptoJS.DES.decrypt({
ciphertext: CryptoJS.enc.Base64.parse(secretText)
}, keyHex, {
mode: CryptoJS.mode.ECB
});
console.info('decrypted :', decrypted);
var plaintext = decrypted.toString(CryptoJS.enc.Utf8);
console.info('plaintext :', plaintext);
But nothing to do, i'm not able to get right result.
I think that problem happen because php use EDE3 mode, and i haven't found any way to use that mode with cryptoJS.
Any suggestion or any other sample to decrypt DES-EDE3 string?
Thank you!
I am trying to encrypt a message from client and decrypt it on the server. I put the AES key and iv in users cookies.
The problem is that the encrypted string from Crypto.js is G0eNQap/h6u+7566MTOH3w==, and the encrypted string from .NET is F7RemlJeNBhcaZ/FjCK4xw==. It has the same length, but not the same value.
I gues I am doing something wrong with encoding. Could you point out the mistake? Thanks in advance.
Crypto.js
var communicationKey = CryptoJS.enc.Base64.parse(getCookie("SessionKey"));
var communicationIV = CryptoJS.enc.Base64.parse(getCookie("IV"));
var encrypted = CryptoJS.AES.encrypt("Message", communicationKey, {
iv: communicationIV,
mode: CryptoJS.mode.CFB
});
console.log("Result: " + CryptoJS.enc.Base64.stringify(encrypted.ciphertext));
.NET:
string key = context.Cookies["SessionKey"].Value;
newUser.UserKey = Convert.FromBase64String(key);
string iv = context.Cookies["IV"].Value;
newUser.InitializationVector = Convert.FromBase64String(iv);
byte[] encryptedMessage = EncryptStringToBytes_Aes("Message", source.UserKey, source.InitializationVector);
In your js code you are using CryptoJS.mode.CFB.
If your EncryptStringToBytes_Aes is exact copy of MSDN sample - then it uses CBC AES encryption mode (it is default for AESManaged).
So you have to change either js or C# code for both of them use the same encryption mode.
I try to decrypt an cipher with AES in GCM mode with the SJCL library in Javascript (from within CasperJS).
When I execute the code below the error I receive is:
error: TypeError: 'undefined' is not a function (evaluating 'b.encrypt([0,
0,0,0])')
The code:
var masterkey = '39537496606860671661230109146651832357';
var cipher = 'Sa2Rk3bbdiaI7mO/';
var iv = '59804781381539321505720964105';
var authdata = '199590863504973848417387014842606357793';
var decff = sjcl.mode.gcm.decrypt(masterkey, cipher, iv, authdata);
console.log (decff);
As you can see, I am basically just calling the decrypt function as the SJCL docs told me to.
The encryption was done in python with this code: https://github.com/bozhu/AES-GCM-Python Wich I found is this thread: AES in GCM mode in Python
Is there anything special I have to consider when encrypting in one language and decrypting in another? Im afraid so...
Can I check somehow if the encryption information are valid AES/GCM?
Im not really sure how to proceed here since Im no JS or Python or encryption expert.
For background information:
I try to achieve a more or less secure encryption in pure python (so I can run it on Google App Engine) and the fitting decryption in pure JS.
Thanks for any help.
You cannot directly decrypt try converting your encrypted string, cypher, IV and auth data to bitArray.
const data = sjcl.mode.gcm.decrypt(cipherArray, encryptedBitArray, iv, authArray, 128);
Here 128 is size you can use 256 as well.
Also try to append your IV with the encypted string.
const bitArray = sjcl.codec.base64.toBits(content);
const bitArrayCopy = bitArray.slice(0);
const ivdec = bitArrayCopy.slice(0, 4);
const encryptedBitArray = bitArray.slice(4);
var key = sjcl.codec.base64.toBits("2d73c1dd2f6a3c981afc7c0d49d7b58f");
let cipher = new sjcl.cipher.aes(key);
I am trying to get crypto-js library to encrypt/decrypt a simple message, please see the following jsfiddle (http://jsfiddle.net/6gunq2nx/)
<script>
var encrypted = CryptoJS.AES.encrypt("this is some test", "770A8A65DA156D24EE2A093277530142");
var decrypted = CryptoJS.AES.decrypt(encrypted, "770A8A65DA156D24EE2A093277530142");
alert(decrypted);
</script>
The problem is that, it is not decrypting the message properly, I have tried AES and DES but both do not work, what im I doing wrong? please see below screenshot
It's almost correct. The string you get is a hexadecimal representation of your original string. Try to convert it like this:
var decrypted = CryptoJS.AES.decrypt(encrypted, "770A8A65DA156D24EE2A093277530142").toString(CryptoJS.enc.Utf8);
forked jsfiddle: http://jsfiddle.net/1qgzk9j8/
try this :-
// Replace this with user input (only user should know the passphrase which can be used to decrypt the message)
var passphrase = '770A8A65DA156D24EE2A093277530142';
// Some content that we want to crypt
var content = 'this is some test';
// Use CryptoJS.AES to encrypt content using AES (Advanced Encryption Standard)
var encryptedContent = CryptoJS.AES.encrypt(content, passphrase);
// Use CryptoJS.AES also to decrypt content
var decryptedContent = CryptoJS.AES.decrypt(encryptedContent, passphrase).toString(CryptoJS.enc.Utf8);
alert(encryptedContent);
alert(decryptedContent);
Demo