I have use case where i need to encrypt my data in Openssl and decrypt it in the java application. i need to use this PBEWITHSHA256ANDAES_256 algorithm for it.
not able to use this algo in decryption. how can i do it ?
also i have tried this algo PBEWITHHMACSHA512ANDAES_256. i am not able to encrypt it in OpenSSL with this.
what can be possible solutions for the above scenario ?
String text = "123456ABC";
String algorithm = "PBEWITHSHA256ANDAES_256";
// PBEWITHHMACSHA512ANDAES_128
String password = "abc";
//When
String encryptedText = JasyptCryptographer.encryptText(text, algorithm, password);
String decryptedText = JasyptCryptographer.decryptText(encryptedText, algorithm, password);
//Then
Assertions.assertNotEquals(text, encryptedText);
Assertions.assertEquals(text, decryptedText);
I am facing below error for one issue of above.
org.jasypt.exceptions.EncryptionInitializationException: java.security.NoSuchAlgorithmException: PBEWITHSHA256ANDAES_256 SecretKeyFactory not available
at org.jasypt.encryption.pbe.StandardPBEByteEncryptor.initialize(StandardPBEByteEncryptor.java:773)
at org.jasypt.encryption.pbe.StandardPBEStringEncryptor.initialize(StandardPBEStringEncryptor.java:566)
at org.jasypt.encryption.pbe.StandardPBEStringEncryptor.encrypt(StandardPBEStringEncryptor.java:644)
Related
I'm trying to convert below java code into nodejs.
private static String TRANS_MODE = "Blowfish";
private static String BLOWFISH_KEY = "BLOWFISH_KEY";
public static String encrypt(String password) throws Exception {
SecretKeySpec keySpec = new SecretKeySpec(BLOWFISH_KEY.getBytes("Windows-31J"),TRANS_MODE);
Cipher cipher;
cipher = Cipher.getInstance(TRANS_MODE);
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] passByte;
passByte = cipher.doFinal(password.getBytes("Windows-31J"));
return new String(Hex.encodeHex(passByte));
}
Here is what I was able to figure out-
const crypto = require('crypto');
function encrypt(password)
var fcKey = "BLOWFISH_KEY";
var cipher = crypto.createCipher('BF-CBC', fcKey, "");
var encrypted = cipher.update(password,'ascii','hex');
encrypted += cipher.final('hex');
return encrypted;
I'm not able to get same output. For example if
password= "password01"
Java Code output - fe0facbf8d458adaa47c5fe430cbc0ad
Nodejs Code output - ae5e8238c929b5716566e97fa35efb9b
Can someone help me figure out the problem ??
Notice that crypto.createCipher(algorithm, password[, options]) is deprecated and should not be used.
Where the SecretKeySpec(..) in java takes a binary key as input, the createCipher(..) in js takes a "password" as input, and behind the scene tries to derive a binary key using MD5. So your actually key used in the two programs ends up being different. The js methode
also tries to derive an IV from the password, which is bad practice and different from your java code.
In js you need to use the crypto.createCipheriv() instead. And when you are at it, you also need to consider if an iv is needed - both in Java and in js.
i'm triying encrypt a password. firstly i will set a rsa public key, after encyrpt a password. but my results are not equals between java and javascript code. is there a way or sample. Could you help me? thanks.
here is my javascript code
var rsa = new RSAKey();
rsa.setPublic(rasn, rase);
var res = rsa.encrypt("myPassword");
return restotal;
here is my java code
RSA1 rsa = new RSA1(new BigInteger(rasn.getBytes()),new BigInteger(rase.getBytes()));
String text1 = "myPassword";
BigInteger plaintext = new BigInteger(text1.getBytes());
BigInteger ciphertext = rsa.encrypt(plaintext);
System.out.println(ciphertext);
Not sure what your RSA1 class exactly does, but you can check a nice sample here.
Your results will never be same, because before RSA encryption, your data will be appended with random bytes called padding.
If you want to test your encryption, decrypt the result back with your private key and see if it works. You can do this between javascript and java if you wish.
So i have an android app, and a google app engine server written in python.
The android app needs to send some sensible information to the server, and the way I do that is by doing an http post.
Now i have been thinking about encrypting the data in android before sending it, and decrypting it once it is on the gae server.
This is how i encrypt and decrypt in java :
private static final String ALGO = "AES";
public static String encrypt(String Data) throws Exception {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encVal = c.doFinal(Data.getBytes());
// String encryptedValue = new BASE64Encoder().encode(encVal);
byte[] decoded = Base64.encodeBase64(encVal);
return (new String(decoded, "UTF-8") + "\n");
}
public static String decrypt(String encryptedData) throws Exception {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue =Base64.decodeBase64(encryptedData);
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}
private static Key generateKey() throws Exception {
Key key = new SecretKeySpec(Constant.keyValue, ALGO);
return key;
}
And this is how i try to decrypt on the server (i don't know yet how to do the encryption..maybe you guys can help with that too)
def decrypt(value):
key = b'1234567891234567'
cipher = AES.new(key, AES.MODE_ECB)
msg = cipher.decrypt(value)
return msg
As i looked in the logs, the string test that i get is : xVF79DzOplxBTMCwAx+hoeDJhyhifPZEoACQJcFhrXA= and because it is not a multiple of 16 (idk why, i guess this is because of the java encryption) i get the error
ValueError: Input strings must be a multiple of 16 in lenght
What am i doing wrong?
Why are you not using ssl (aka https)? That should provide all the encryption needed to transport data securely and privately between the phone and App Engine.
The basics of it: Instead of sending data to http://yourapp.appspot.com/, send it to https://yourapp.appspot.com/.
For a complete secure and authenticated channel between App Engine and Android, you can use Google Cloud Endpoints. It will even generate the Android side code to call it.
Java:
https://developers.google.com/appengine/docs/java/endpoints/
https://developers.google.com/appengine/docs/java/endpoints/consume_android
Python:
https://developers.google.com/appengine/docs/python/endpoints/
https://developers.google.com/appengine/docs/python/endpoints/consume_android
For a longer show and tell, check the IO 13 talk: https://www.youtube.com/watch?v=v5u_Owtbfew
This string "xVF79DzOplxBTMCwAx+hoeDJhyhifPZEoACQJcFhrXA=" is a base64-encoded value.
https://en.wikipedia.org/wiki/Base64
Base64 encoding is widely used lots of applications, it's a good way to encode binary data into text. If you're looking at a long encoded value, the "=" at the end can be a good indicator of base64 encoding.
In your python code you probably need to base64 decode the data before handing it to the decryption function.
I have two recommendations:
If crypto isn't a comfort zone for you, consult with someone who is good in this area for your project.
Be aware that embedding a symmetric encryption key in an Android app that you distribute is a bad idea. Anyone that can get a copy of your app can extract that key and use it to decrypt or spoof your messages.
I have keys created in Java. The private key is PKCS#8 encrypted, in PEM string.
Here is an example of using the private key with M2Crypto in Python:
from M2Crypto import EVP, BIO
privpem = "-----BEGIN ENCRYPTED PRIVATE KEY-----\nMIICoTAbBgoqhkiG9w0BDAEDMA0ECFavEvdkv3fEAgEUBIICgAWvHvH6OktLiaaqo9v+X6XEuY3M\nZr465VmZWzP9nsbTqwSKQQjseiD/rWAxK7RS+V+hit5ZxlNRAUbkg0kwl8SRNX3v6q8noJtcB0OY\ndBEuNJDmWHMHh8qcnfRYc9WXPPmWdjQM2AkfZNfNOxHVlOMhancScy6P4h3Flri9VyUE8w2/zZqK\nBAd2w39V7gprCQXnnNenNuvr4p8MjsdBm8jh00o2HJzN0I6u+9s7M3qLXxwxNepptgU6Qt6eKHi6\njpsV/musVaohLhFMFAzQ87FeGvz/W8dyS9BtAKMRSuDu/QdWIJMRNKkPT0Tt1243V3tzXVXLjz0u\nm/FX6kfxL8r+eGtTr6NKTG75TJfooQzN/v08OEbmvYD/mfptmZ7uKezOGxDmgynn1Au7T/OxKFhx\nWZHpb9OFPIU0uiriUeyY9sbDVJ054zQ/Zd5+iaIjX5RsLoB4J+pfr4HuiVIZVj+Ss2rnPsOY3SjM\ntbHIFp/fLr/HODcDA5eYADRGpBIL9//Ejgzd7OqpU0mdajzZHcMTjeXfWB0cc769bFyHb3Ju1zNO\ng4gNN1H1kOMAXMF7p6r25f6v1BRS6bQyyiFz7Hs7h7JBylbBAgQJgZvv9Ea3XTMy+DIPMdepqu9M\nXazmmYJCtdLAfLBybWsfSBU5K6Pm6+Bwt6mPsuvYQBrP3h84BDRlbkntxUgaWmTB4dkmzhMS3gsY\nWmHGb1N+rn7xLoA70a3U/dUlI7lPkWBx9Sz7n8JlH3cM6jJUmUbmbAgHiyQkZ2mf6qo9qlnhOLvl\nFiG6AY+wpu4mzM6a4BiGMNG9D5rnNyD16K+p41LsliI/M5C36PKeMQbwjJKjmlmWDX0=\n-----END ENCRYPTED PRIVATE KEY-----\n"
msg = "This is a message."
privkeybio = BIO.MemoryBuffer(privpem)
privkey = EVP.load_key_bio(privkeybio) #pw: 123456
privkey.sign_init()
privkey.sign_update(msg)
print privkey.sign_final().encode('base64')
And here is example of how I can use the PEM (with header and footer stripped off) in Java:
String msg = "This is a message.";
String privpem = "MIICoTAbBgoqhkiG9w0BDAEDMA0ECFavEvdkv3fEAgEUBIICgAWvHvH6OktLiaaqo9v+X6XEuY3M\nZr465VmZWzP9nsbTqwSKQQjseiD/rWAxK7RS+V+hit5ZxlNRAUbkg0kwl8SRNX3v6q8noJtcB0OY\ndBEuNJDmWHMHh8qcnfRYc9WXPPmWdjQM2AkfZNfNOxHVlOMhancScy6P4h3Flri9VyUE8w2/zZqK\nBAd2w39V7gprCQXnnNenNuvr4p8MjsdBm8jh00o2HJzN0I6u+9s7M3qLXxwxNepptgU6Qt6eKHi6\njpsV/musVaohLhFMFAzQ87FeGvz/W8dyS9BtAKMRSuDu/QdWIJMRNKkPT0Tt1243V3tzXVXLjz0u\nm/FX6kfxL8r+eGtTr6NKTG75TJfooQzN/v08OEbmvYD/mfptmZ7uKezOGxDmgynn1Au7T/OxKFhx\nWZHpb9OFPIU0uiriUeyY9sbDVJ054zQ/Zd5+iaIjX5RsLoB4J+pfr4HuiVIZVj+Ss2rnPsOY3SjM\ntbHIFp/fLr/HODcDA5eYADRGpBIL9//Ejgzd7OqpU0mdajzZHcMTjeXfWB0cc769bFyHb3Ju1zNO\ng4gNN1H1kOMAXMF7p6r25f6v1BRS6bQyyiFz7Hs7h7JBylbBAgQJgZvv9Ea3XTMy+DIPMdepqu9M\nXazmmYJCtdLAfLBybWsfSBU5K6Pm6+Bwt6mPsuvYQBrP3h84BDRlbkntxUgaWmTB4dkmzhMS3gsY\nWmHGb1N+rn7xLoA70a3U/dUlI7lPkWBx9Sz7n8JlH3cM6jJUmUbmbAgHiyQkZ2mf6qo9qlnhOLvl\nFiG6AY+wpu4mzM6a4BiGMNG9D5rnNyD16K+p41LsliI/M5C36PKeMQbwjJKjmlmWDX0=";
byte [] privkeybytes = Base64.decode(privpem);
EncryptedPrivateKeyInfo encprivki = new EncryptedPrivateKeyInfo(privkeybytes);
Cipher cipher = Cipher.getInstance(encprivki.getAlgName());
PBEKeySpec pbeKeySpec = new PBEKeySpec("123456".toCharArray());
SecretKeyFactory secFac = SecretKeyFactory.getInstance(encprivki.getAlgName());
Key pbeKey = secFac.generateSecret(pbeKeySpec);
AlgorithmParameters algParams = encprivki.getAlgParameters();
cipher.init(Cipher.DECRYPT_MODE, pbeKey, algParams);
KeySpec pkcs8KeySpec = encprivki.getKeySpec(cipher);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey pk = kf.generatePrivate(pkcs8KeySpec);
Signature sig = Signature.getInstance("SHA1withRSA");
sig.initSign(pk);
sig.update(msg.getBytes("UTF8"));
byte[] signatureBytes = sig.sign();
String b = Base64.encodeBytes(signatureBytes, Base64.DO_BREAK_LINES);
System.out.println(b); // Display the string.
How would this be done in iOS? I have looked at the CryptoExercise, in particular the SecKeyWrapper, but there is lots going on there, and it's beyond me.
I am not personally going to be doing the iOS development, but I need some code to give to the developer to at least show more or less how to do it. The developer is more a UI type and not familiar with crypto. (Neither am I but that is a different story...)
And while we're at it, how to verify a signature against a string public key PEM? I won't put the Java and Python examples here as they are pretty straight forward.
I had the same problem last week. The CommonCrypt library on iOS is very nice for symmetric key encryption, but it's just too much hassle dealing with the keyring to do simple public key things. After spending about half an hour poking at it I just included OpenSSL. OpenSSL-Xcode made this trivial to set up - just drop the project and the OpenSSL tarball in, set your target to link with libssl, and you're good to go.
The OpenSSL code looks nearly the same as the M2Crypto one.
I want tp encrypt and decrypt string, with defined salt. But the result must be same if the code run in java and adobe flex.
The main goal is: the app in adobe flex will be generate a string that can be decrypt in server using java.
I use this flex library
http://crypto.hurlant.com/demo/
Try to 'Secret Key' Tab. I want to use AES Encryption, 'CBC' or 'PKCS5'.
var k:String = "1234567890123456";
var kdata:ByteArray = Hex.toArray(k);
var txt:String = "hello";
var data:ByteArray = Hex.toArray(Hex.fromString(txt));;
var name:String = "simple-aes-cbc";
var pad:IPad =new PKCS5();
var mode:ICipher = Crypto.getCipher(name, kdata, pad);
pad.setBlockSize(mode.getBlockSize());
mode.encrypt(data);
encrypted.text=Hex.fromArray(data);
trace(Hex.fromArray(data));
And here is the code in java
String plaintext = "hello";
String key = "1234567890123456";
SecretKey keyspec = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE,keyspec);
byte[] encrypted = cipher.doFinal(plaintext.getBytes());
BASE64Encoder base64 = new BASE64Encoder();
String encodedString = base64.encode(encrypted);
System.out.println(encodedString);
Why the result is not same?
Can you guys provide the sample with the same result both of java and flex (encrypt and decrypt)? And if I want to change the paramater, for example, from cbc to ebc, which line that need to be changed?
Thanks!
"Simple" encryption mode (simple-aes-cbc) uses random initialization vector which is different each time you use it even if your secret key is the same.
If you wish to guarantee the same results when using the same key you should use "aes-cbc". Additionally you have to manually set the IV on the Cipher:
var ivmode:IVMode = mode as IVMode;
ivmode.IV = "some string guaranteed to be constant"
The IV can be made dependent on something like userId, which makes encryption repeatable for the same user.
You should consider how this affects your security scheme.
Seems like I do not convert into hex first in java when pass the key. And so on when get result byteArray at adobe flex, I do not cast again in java.
That's what I got when I see Arcadio code. Thanks.