I use AES algoritm to make a udp request in local subnet (192.168.1.x).
The Playstore shows me a warning because I use static secret key.
// Console alert refers to this method
public byte[] encryptionUtil(String key, String iv, byte[] plainText) {
Cipher cipher = Cipher.getInstance(“AES/GCM/NoPadding”);
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), “AES”);
GCMParameterSpec paramSpec = new GCMParameterSpec(256, iv.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, keySpec, paramSpec);
return cipher.doFinal(plainText);
}
// The unsafe key and initialisation vector are here and should be changed
byte[] cipherText = encryptionUtil(“abcdef...”, “010203040506”, plainText);
I'm try to make a iv random and send it in the udp packet, I publish the apk again but the playstore make the warning again.
What is the solution?
Related
I've been tasked to fix an interoping encryption algorithm that was working perfectly fine from before but suddenly went haywire for reasons unknown, no one has touched any of the code for both of the languages (Java & JS).
I'm not really well verse with cryptography so I don't know what possible solutions to look for or work with. The task was basically to have this encryption code on Java translated to JavaScript that would both have a resulting Base64 string that was to be decrypted through Java.
The following are the code snippets for the encryption being done with Java & JS and decryption process on Java:
Java Encryption
public static String encryptMsg(String message) {
#SuppressLint("GetInstance") Cipher cipher = null;
try {
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
byte[] cipherText = cipher.doFinal(message.getBytes(UTF_CHARSET));
return Base64.encodeToString(cipherText, Base64.DEFAULT);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException e) {
e.printStackTrace();
} catch (NullPointerException e) {
//Do nothing, nothing to encrypt
}
return null;
}
JavaScript Encryption
function encryptData(data, key) {
const options = {
mode: Crypto.mode.ECB,
padding: Crypto.pad.Pkcs7
}
const secret = Crypto.enc.Utf8.parse(key)
const encrypted = Crypto.AES.encrypt(data, secret, options)
return encrypted.ciphertext.toString(Crypto.enc.Base64)
}
Java Decryption
public static String decryptMsg(String base64cipherText) {
#SuppressLint("GetInstance") Cipher cipher = null;
try {
cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, secret);
String decryptString = new String(cipher.doFinal(Base64.decode(base64cipherText, Base64.DEFAULT)), UTF_CHARSET);
return decryptString;
} catch (NoSuchAlgorithmException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException e) {
e.printStackTrace();
} catch (NullPointerException e) {
//Do nothing, nothing to decrypt
}
return null;
}
Currently the results return null on the encrypted string using the JavaScript encryption function when being decrypted so it's probably encrypting correctly(?) I'm not sure what I'm missing or doing wrong here...
Seems you are missing IV (initialization vector).
don't really know what an IV is or if it's needed here, the encryption Java code doesn't state it anywhere
The IV is an initialization vector allowing to reuse a key to encrypt multiple messages (or blocks), please have a look at the CBC block mode as you are using it.
I am not sure for JavaScript API, but at least I can give you example in Java. As well you can have a look at my blog about crypto examples
Java Encryption
SecureRandom rnd = new SecureRandom();
byte[] iv = new byte[SYMMETRIC_BLOCK_SIZE / 8];
IvParameterSpec ivParamSpec = new IvParameterSpec(iv);
SecretKey symmetricKey = new SecretKeySpec(encryptionParams.getKey(), SYMMETRIC_KEY_ALG);
Cipher cipher = Cipher.getInstance(SYMMETRIC_CIPHER_NAME);
cipher.init(Cipher.ENCRYPT_MODE, symmetricKey, ivParamSpec);
byte[] encrypted = cipher.doFinal(encryptionParams.getPlaintext());
/* and encoded form can contain form of base64( IV + ciphertext ) */
For CBC mode the IV must be random. If you don't specify the IVParameter, it will be generated and you can read it from cipher.getIV();. The IV can be public, it is usually prepended before the ciphertext, as the IV is needed to decrypt the ciphertext itself.
Java Decryption
/* if IV is prepended before the ciphertext, it can be fetched as sub-array
of the decoded message */
IvParameterSpec ivParamSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance(SYMMETRIC_CIPHER_NAME);
cipher.init(Cipher.DECRYPT_MODE, symmetricKey, ivParamSpec);
byte[] decrypted = cipher.doFinal(encryptionParams.getCiphertext());
In this example there's no Mac (message authentication code included), you can have a look at the linked example.
For JavaScript you should have a look at the used API, but the principle stays the same (you have to generate, use, pass and provide the IV too somehow). This blog seems to contain be more complete code.
var iv = CryptoJS.lib.WordArray.random(128/8);
var encrypted = CryptoJS.AES.encrypt(msg, key, {
iv: iv,
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC
});
I'm getting the following exception when i try to encrypt a byte array with a EC public key :
java.security.InvalidKeyException: No installed provider supports this key:
sun.security.ec.ECPublicKeyImpl
This exception is generated when i call Cipher.init(). The lines below show what I did in my program:
ECPublicKey publicKey ;
ECPrivateKey privateKey;
//Generating key paire (public and private keys)
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC", "SunEC");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
keyGen.initialize(571, random);
KeyPair pair = keyGen.generateKeyPair();
privateKey = (ECPrivateKey) pair.getPrivate();
publicKey = (ECPublicKey) pair.getPublic();
// get an AES cipher object with CTR encription mode
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
// encrypt the sharedSecret using the public key
cipher.init(Cipher.ENCRYPT_MODE, publicKey);**
byte[] result = cipher.doFinal(data);
Must I add a provider to support this public key ??
Finally, I found the source of this exception. The problem was initialization of cipher :
//This is the wrong initialization
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
//This is the right initialization
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding","SunJCE");
But now, i have another exception which is (it is less important than the previous one) :
java.security.InvalidKeyException: Invalid AES key length: 170 bytes
So what must I use as encrypting algorithm with ECDSA public key now ?
I would like to use encryption to send traffic to my F5 BIG IP load balancer and have it use its own native CRYPTO:: methods to decrypt a base64 encoded string.
I am able to encrypt and decrypt a string within the appliance and within a Visual Studio 2012 console application but I cannot decrypt an encrypted string in the opposing environment.
Any suggestion here as to how to get the following keys in a compatible format that CRYPTO or C# understands would go a long way!
// C# key and vector declaration:
private const string AesIV = #"!QAZ2WSX#EDC4RFV";
private const string AesKey = #"5TGB&YHN7UJM(IK<";
It appears that in CRYPTO:: it needs it in hex format, I tried to convert it as seen below but that didnt help me.
C# console app code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Security.Cryptography;
using System.Threading;
namespace ssoconsole_encrypt
{
class Program
{
private const string AesIV = #"!QAZ2WSX#EDC4RFV";
private const string AesKey = #"5TGB&YHN7UJM(IK<";
// set key "abed1ddc04fbb05856bca4a0ca60f21e"
//set iv "d78d86d9084eb9239694c9a733904037"
// set key "56bca4a0ca60f21e"
// set iv "39694c9a73390403"
/// <summary>
/// AES Encryption
/// </summary>
///
static public string Encrypt(string text)
{
// AesCryptoServiceProvider
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.IV = Encoding.UTF8.GetBytes(AesIV);
aes.Key = Encoding.UTF8.GetBytes(AesKey);
string keyme = BitConverter.ToString(aes.Key);
string ivme = BitConverter.ToString(aes.IV);
Console.WriteLine(string.Format("The converted key is: {0}",keyme));
Console.WriteLine(string.Format("The converted iv is: {0}", ivme));
Console.WriteLine(System.Text.Encoding.UTF8.GetString(aes.Key));
// Thread.Sleep(10000);
//Console.WriteLine(aes.Key.ToString());
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
// aes.Padding = PaddingMode.Zeros;
// Convert string to byte array
//byte[] src = Encoding.Unicode.GetBytes(text);
byte[] src = Encoding.UTF8.GetBytes(text);
// encryption
using (ICryptoTransform encrypt = aes.CreateEncryptor())
{
byte[] dest = encrypt.TransformFinalBlock(src, 0, src.Length);
// Convert byte array to Base64 strings
return Convert.ToBase64String(dest);
}
}
/// <summary>
/// AES decryption
/// </summary>
static public string Decrypt(string text)
{
// AesCryptoServiceProvider
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.IV = Encoding.UTF8.GetBytes(AesIV);
aes.Key = Encoding.UTF8.GetBytes(AesKey);
//aes.IV = Encoding.UTF8.GetBytes(#"01020304050607080900010203040506");
//aes.Key = Encoding.UTF8.GetBytes(#"01020304050607080900010203040506");
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
// Convert Base64 strings to byte array
byte[] src = System.Convert.FromBase64String(text);
try
{
// decryption
using (ICryptoTransform decrypt = aes.CreateDecryptor())
{
byte[] dest = decrypt.TransformFinalBlock(src, 0, src.Length);
// return Encoding.Unicode.GetString(dest);
return Encoding.UTF8.GetString(dest);
}
}
catch (CryptographicException e)
{
return e.ToString();
}
}
static void Main()
{
string username = "jschoombee";
string encrypted = Encrypt(username);
string decrypted = Decrypt(encrypted);
// string decrypted = Decrypt("epvhTN55JnnVV9DBn1Cbsg==");
// string decrypted = Decrypt(encrypted);
Console.WriteLine(string.Format("jschoombee encrypted is : {0}",encrypted));
Console.WriteLine(string.Format("the Decrypted username for jp is : {0}", decrypted));
Thread.Sleep(1000000);
}
}
}
This is the Console Output:
The converted key is: 35-54-47-42-26-59-48-4E-37-55-4A-4D-28-49-4B-3C
The converted iv is: 21-51-41-5A-32-57-53-58-23-45-44-43-34-52-46-56
5TGB&YHN7UJM(IK<
jschoombee encrypted is : tGG9Un6VqcAOTQawlxwRXg==
the Decrypted username for jp is : jschoombee
This it the F5 / TCL code:
when RULE_INIT {
set static::hexkey "355447422659484E37554A4D28494B3C"
log local0.info"====Rule_Init===="
log local0.info "Key is $static::hexkey"
log local0.info"================="
}
when HTTP_REQUEST_DATA {
set iv "2151415A325753582345444334524656"
set text_to_encrypt "jschoombee"
set enc_out_no_binary [CRYPTO::encrypt -alg aes-256-cbc -keyhex $static::hexkey -ivhex $iv $text_to_encrypt]
set dec_in [CRYPTO::decrypt -alg aes-256-cbc -keyhex $static::hexkey -ivhex $iv $enc_out_no_binary]
log local0.info "The decrypted NO binary $dec_in"
log local0.info "The Encrypted NO binary Base64 is: [b64encode "$enc_out_no_binary"]"
binary scan $enc_out_no_binary H* enc_hex
log local0.info "The Encrypted NO binary Hex is: $enc_hex"
log local0.info "This is the IV $iv"
HTTP::release
}
The F5/TCL Output Log File:
Feb 11 13:05:45 AMS4-LB-01 info tmm1[9650]: <HTTP_REQUEST_DATA>: The decrypted NO binary jschoombee
Feb 11 13:05:45 AMS4-LB-01 info tmm1[9650]: <HTTP_REQUEST_DATA>: The Encrypted NO binary Base64 is: Rlz4cC9SlpRyON4cZI+dtQ==
Feb 11 13:05:45 AMS4-LB-01 info tmm1[9650]: <HTTP_REQUEST_DATA>: The Encrypted NO binary Hex is: 465cf8702f5296947238de1c648f9db5
Feb 11 13:05:45 AMS4-LB-01 info tmm1[9650]: <HTTP_REQUEST_DATA>: This is the IV 2151415A325753582345444334524656
There are some very strange things happening in your code regarding the key and IV.
First of all the key you've specified is 16 characters. In UTF-8 those result in 16 bytes. You are however specifying a key of 32 bytes (256 bits) in your C# code. Also be warned that many libraries (incorrectly) use AES-256 to mean Rijndael with a 256 bit block size. It's probably better to just use AES-128 and focus on making your protocol and code secure.
Second, a key can never be a character string. A character string normally is restricted with regards to which values can be used. E.g. control codes cannot be entered. This means that your key will never reach its intended strength. If you want to use a static key, you should specify it in hexadecimals as you do in your F5 code.
A static IV does not make much sense. The whole idea of the IV is to make sure that you will generate a different ciphertext if you encrypt a block with a value already processed. So please use a random IV, and place it in front of your ciphertext.
You seem to have the hang on using encoding/decoding on your plaintext (UTF-8) and ciphertext (Base 64). So please try and follow the advice given above and try again.
I have to write a standalone java program to decrypt password from file,using Symmetric key for password decryption. I didn't work with encryption and decryption before. can anybody give any suggestion how can i do this.I need your guidance.
maybe you need something like this
private static final String ALGORITHM = "AES";
....
....
Key key = new SecretKeySpec(new String("here is your symmetric key").getBytes(), ALGORITHM);
Cipher c = Cipher.getInstance(ALGORITHM);
//dencript mode (passes the key)
c.init(Cipher.DECRYPT_MODE, key);
//Decode base64 to get bytes
byte[] encBytes = new BASE64Decoder().decodeBuffer(encryptedValue);
// Decrypt
byte[] plainTxtBytes = c.doFinal(encBytes);
// Decode
String decryptedValue = new String(plainTxtBytes , "UTF-8");
Here are some resources:
http://www.javamex.com/tutorials/cryptography/symmetric.shtml
http://www.java2s.com/Code/Java/Security/EncryptionandDecryptionusingSymmetricKeys.htm
http://www.flexiprovider.de/examples/ExampleCrypt.html (This uses files as well)
Following is my Java applet code
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] privKeyBytes = loadPriavteKeyFromFile(fileName, new String(txtPassword.getPassword()));
PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(privKeyBytes);
RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(privSpec);
Cipher rsaCipher = Cipher.getInstance("RSA");
rsaCipher.init(Cipher.ENCRYPT_MODE, privKey);
byte[] ciphertext = null;
ciphertext = rsaCipher.doFinal(xmlToSign.getBytes());
String urlString = "http://localhost:3290/SignApplet.aspx";
String senddata = Base64.encodeBase64String(ciphertext);
doHttpUrlConnectionAction(urlString,senddata.getBytes());
JOptionPane.showMessageDialog(this, "XML successfully signed and sent to server.");
on the server side i am trying too decrypt the byte using the public key
byte[] b;
b = Request.BinaryRead(178);
string encodedbytes = new System.Text.UTF8Encoding().GetString(b);
b = Convert.FromBase64String(encodedbytes);
Debug.WriteLine("decrypted bytes:" + new System.Text.UTF8Encoding().GetString(b));
// The path to the certificate.
string Certificate = #"c:\certs\lafa801114sd3.cer";
//// Load the certificate into an X509Certificate object.
X509Certificate cert = new X509Certificate(Certificate);
RSACryptoServiceProvider publicprovider = (RSACryptoServiceProvider)CertUtil.GetCertPublicKey(cert);
byte[] decbytes = publicprovider.Decrypt(b, false);
Debug.WriteLine("decrypted bytes" + new System.Text.UTF8Encoding().GetString(decbytes));
can any one help in following exception which i am getting at byte[] decbytes = publicprovider.Decrypt(b, false); line
A first chance exception of type 'System.Security.Cryptography.CryptographicException' occurred in mscorlib.dll
Key does not exist.
and the certificate is not installed in nay key store.Also i can successfully decrypt the data using Java servlet .
i am using asp.net vs2010 on windows 7
the public and private keys are stored in separate files
Here are a few articles that might help you: Java RSA Encrypt - Decrypt .NET (which seems like what you are looking for)
and http://www.jensign.com/JavaScience/dotnet/RSAEncrypt/