I have this code in C # which generates an encrypted password.
I would like to make it compatible in Java.
Code C#
private static string ccs = "&Ux#B*******";
private static ICryptoTransform __Get_AES128_Transform(string password, bool AsDecryptor)
{
const int KEY_SIZE = 16;
var sha256CryptoServiceProvider = new SHA256CryptoServiceProvider();
var hash = sha256CryptoServiceProvider.ComputeHash(Encoding.Unicode.GetBytes(password));
var key = new byte[KEY_SIZE];
var iv = new byte[KEY_SIZE];
Buffer.BlockCopy(hash, 0, key, 0, KEY_SIZE);
if (AsDecryptor)
return new AesCryptoServiceProvider().CreateDecryptor(key, iv);
else
return new AesCryptoServiceProvider().CreateEncryptor(key, iv);
}
public static string Encrypt(this string Value)
{
byte[] Buffer = Encoding.Unicode.GetBytes(Value);
using (ICryptoTransform transform = __Get_AES128_Transform(ccs, false))
{
byte[] encyptedBlob = transform.TransformFinalBlock(Buffer, 0, Buffer.Length);
return Convert.ToBase64String(encyptedBlob);
}
}
Could anyone give a direction to decrypt in java?
My answer interoperable encrypt, I hope this helps you. Result can be decrypted from any platform - C# code or Android/Java code.
Encrypt from C# -> Decrypt from C#, Android, Java.
Encrypt from Android -> Decrypt from Android, Java, C#.
Encrypt from Java -> Decrypt from Java, Android, C#.
The result of encrypt contains the encrypted text + IV.
IV is generated using secure random algoritm.
Encrypt process
Transform plaintext => plaintextBytes
Transform password => passwordBytes => Sha256(passwordbytes) = passwordHashBytes
generate random IV bytes = ivBytes
encrypt using plaintextbytes and passwordHashBytes
join (encryptedbytes + ivBytes)
Transform to base64 joined bytes.
Decrypt process
Transform base64 string to bytes.
Split array encryptedBytes, ivBytes
Transform password => passwordBytes => Sha256(passwordbytes) = passwordHashBytes
Decrypt using ivBytes, EncryptedBytes, PasswordHashBytes
Transform DecryptedBytes to String
The IV is randomized in every Encrypt process to get different output with same text and avoid to intruders/attackers get original text easily.
The default mode is CBC.
The encoding used is UTF-8. UTF-8 is the most widely used encoding on the web. Check Usage of character encodings broken down by ranking
References
Initialization vector
Block cipher mode of operation
C# Implementation
using System;
using System.Security.Cryptography;
using System.Text;
public enum HashAlgorithm
{
MD5,
SHA1,
SHA256,
SHA384,
SHA512
}
public class HashManager
{
public static byte[] ToRawHash(byte[] data, HashAlgorithm algorithm)
{
byte[] hash;
switch (algorithm)
{
case HashAlgorithm.MD5:
MD5 md5 = MD5.Create();
hash = md5.ComputeHash(data, 0, data.Length);
return hash;
case HashAlgorithm.SHA1:
SHA1Managed sha1 = new SHA1Managed();
hash = sha1.ComputeHash(data);
return hash;
case HashAlgorithm.SHA256:
SHA256Managed sha256 = new SHA256Managed();
hash = sha256.ComputeHash(data);
return hash;
case HashAlgorithm.SHA384:
SHA384Managed sha384 = new SHA384Managed();
hash = sha384.ComputeHash(data);
return hash;
case HashAlgorithm.SHA512:
SHA512Managed sha512 = new SHA512Managed();
hash = sha512.ComputeHash(data, 0, data.Length);
return hash;
default:
throw new ArgumentException("Invalid Algorithm");
}
}
}
public class AesManager
{
private const int MAX_IV_LENGTH = 16;
private const int MAX_KEY_LENGTH = 32;
private static byte[] GenerateValidKey(byte[] keyBytes)
{
byte[] ret = new byte[MAX_KEY_LENGTH];
byte[] hash = HashManager.ToRawHash(keyBytes, HashAlgorithm.SHA256);
Array.Copy(hash, ret, MAX_KEY_LENGTH);
return ret;
}
public static byte[] EncryptRaw(byte[] PlainBytes, byte[] Key)
{
AesManaged AesAlgorithm = new AesManaged()
{
Key = GenerateValidKey(Key)
};
AesAlgorithm.GenerateIV();
var Encrypted = AesAlgorithm.CreateEncryptor().TransformFinalBlock(PlainBytes, 0, PlainBytes.Length);
byte[] ret = new byte[Encrypted.Length + MAX_IV_LENGTH];
Array.Copy(Encrypted, ret, Encrypted.Length);
Array.Copy(AesAlgorithm.IV, 0, ret, ret.Length - MAX_IV_LENGTH, MAX_IV_LENGTH);
return ret;
}
public static byte[] DecryptRaw(byte[] CipherBytes, byte[] Key)
{
AesManaged AesAlgorithm = new AesManaged()
{
Key = GenerateValidKey(Key)
};
byte[] IV = new byte[MAX_IV_LENGTH];
Array.Copy(CipherBytes, CipherBytes.Length - MAX_IV_LENGTH, IV, 0, MAX_IV_LENGTH);
AesAlgorithm.IV = IV;
byte[] RealBytes = new byte[CipherBytes.Length - MAX_IV_LENGTH];
Array.Copy(CipherBytes, RealBytes, CipherBytes.Length - MAX_IV_LENGTH);
return AesAlgorithm.CreateDecryptor().TransformFinalBlock(RealBytes, 0, RealBytes.Length); ;
}
public static String EncryptToBase64(String Plaintext, String Key)
{
byte[] PlainBytes = Encoding.UTF8.GetBytes(Plaintext);
return Base64Manager.ToBase64(EncryptRaw(PlainBytes, Encoding.UTF8.GetBytes(Key)), false);
}
public static String DecryptFromBase64(String CipherText, String Key)
{
byte[] CiPherBytes = Base64Manager.Base64ToByteArray(CipherText);
byte[] Encrypted = DecryptRaw(CiPherBytes, Encoding.UTF8.GetBytes(Key));
return Encoding.UTF8.GetString(Encrypted, 0, Encrypted.Length);
}
}
public class Base64Manager
{
public static byte[] Base64ToByteArray(String base64)
{
return Convert.FromBase64String(base64);
}
public static String ToBase64(byte[] data, Boolean insertLineBreaks = default(Boolean))
{
return insertLineBreaks ? Convert.ToBase64String(data, Base64FormattingOptions.InsertLineBreaks) : Convert.ToBase64String(data);
}
}
public class Program
{
public static void Main()
{
string plainText = "plain text";
string password = "password";
string encrypted = AesManager.EncryptToBase64(plainText, password);
Console.WriteLine(encrypted);
Console.WriteLine(AesManager.DecryptFromBase64(encrypted, password));
Console.ReadLine();
}
}
Android/Java Implementation
public enum HashAlgorithm {
SHA512("SHA-512"),
SHA256("SHA-256"),
SHA384("SHA-384"),
SHA1("SHA-1"),
MD5("MD5");
private String Value = "";
HashAlgorithm(String Value) {
this.Value = Value;
}
#Override
public String toString() {
return Value;
}
}
import java.security.MessageDigest;
public class HashManager {
public static byte[] toRawHash(byte[] data,
HashAlgorithm algorithm) throws Exception
{
byte[] buffer = data;
MessageDigest messageDigest = MessageDigest.getInstance(algorithm.toString());
messageDigest.reset();
messageDigest.update(buffer);
return messageDigest.digest();
}
}
Base64Manager class Android implementation
import android.util.Base64;
public class Base64Manager {
public static String toBase64(byte[] data,
boolean insertLineBreaks) throws Exception
{
String ret;
if (insertLineBreaks)
{
ret = Base64.encodeToString(data, Base64.DEFAULT);
}
else
{
ret = Base64.encodeToString(data, Base64.NO_WRAP);
}
return ret;
}
public static String toBase64(String data,
boolean insertLineBreaks) throws Exception
{
return toBase64(data.getBytes("UTF-8"), insertLineBreaks);
}
public static byte[] base64ToByteArray(String base64) throws Exception
{
return base64.contains(System.getProperty("line.separator")) ? Base64.decode(base64, Base64.DEFAULT) : Base64.decode(base64, Base64.NO_WRAP);
}
}
Base64Manager class Java8+ implementation
import java.util.Base64;
public class Base64Manager {
public static String toBase64(byte[] data, Boolean insertLineBreaks) throws Exception {
String ret;
if (insertLineBreaks) {
ret = Base64.getMimeEncoder().encodeToString(data);
} else {
ret = Base64.getEncoder().encodeToString(data);
}
return ret;
}
public static String toBase64(String data, Boolean insertLineBreaks) throws Exception {
return toBase64(data.getBytes("UTF-8" ), insertLineBreaks);
}
public static byte[] base64ToByteArray(String base64) throws Exception {
return base64.contains(System.getProperty("line.separator")) ? Base64.getMimeDecoder().decode(base64) : Base64.getDecoder().decode(base64);
}
}
import java.security.SecureRandom;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AesManager {
private static final int MAX_IV_LENGTH = 16;
private static final int MAX_KEY_LENGTH = 32;
public static String decryptFromBase64(String cipherText, String key) throws Exception {
byte[] CiPherBytes = Base64Manager.base64ToByteArray(cipherText);
byte[] KeyBytes = key.getBytes("UTF-8");
return new String((decryptRaw(CiPherBytes, KeyBytes)));
}
public static byte[] generateValidKey(byte[] key) throws Exception {
return Arrays.copyOf(HashManager.toRawHash(key, HashAlgorithm.SHA256), MAX_KEY_LENGTH);
}
public static byte[] decryptRaw(byte[] cipherBytes, byte[] keyBytes) throws Exception {
byte[] IV = Arrays.copyOfRange(cipherBytes, cipherBytes.length - MAX_IV_LENGTH, cipherBytes.length);
byte[] RealBytes = Arrays.copyOf(cipherBytes, cipherBytes.length - MAX_IV_LENGTH);
Cipher AesAlgorithm = Cipher.getInstance("AES/CBC/PKCS5Padding" );
byte[] ValidKeyBytes = generateValidKey(keyBytes);
SecretKeySpec secretKeySpec = new SecretKeySpec(ValidKeyBytes, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(IV);
AesAlgorithm.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] Decrypted = AesAlgorithm.doFinal(RealBytes);
return Decrypted;
}
public static byte[] encryptRaw(byte[] plainBytes, byte[] keyBytes) throws Exception {
Cipher AesAlgorithm = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] ValidKeyBytes = generateValidKey(keyBytes);
SecretKeySpec secretKeySpec = new SecretKeySpec(ValidKeyBytes, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(generateIV());
AesAlgorithm.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] Encrypted = AesAlgorithm.doFinal(plainBytes);
byte[] ret = new byte[Encrypted.length + MAX_IV_LENGTH];
System.arraycopy(Encrypted, 0, ret, 0, Encrypted.length);
System.arraycopy(ivParameterSpec.getIV(), 0, ret, Encrypted.length, MAX_IV_LENGTH);
return ret;
}
private static byte[] generateIV() throws Exception {
return generateRandomArray(MAX_IV_LENGTH);
}
public static byte[] generateRandomArray(int size) {
SecureRandom RandomGenerator = new SecureRandom();
byte[] ret = new byte[size];
RandomGenerator.nextBytes(ret);
return ret;
}
public static String encryptToBase64(String plaintext, String key) throws Exception {
byte[] PlainBytes = plaintext.getBytes("UTF-8");
byte[] KeyBytes = key.getBytes("UTF-8");
return Base64Manager.toBase64(encryptRaw(PlainBytes, KeyBytes), false);
}
}
public class Program {
public static void main(String[] args) throws Exception
{
String plainText = "plain text";
String password = "password";
String encrypted = AesManager.encryptToBase64(plainText, password);
System.out.println(encrypted);
System.out.println(AesManager.decryptFromBase64(encrypted, password));
}
}
Output
Java
PS C:\Users\Megam\OneDrive\Documentos\NetBeansProjects\TestAes\target> java -cp .\TestAes-1.0-SNAPSHOT.jar com.mycompany.testaes.Program
leHBoUoB54bd9JEa9s9INohjVjmb2RZqVzrz2uYEstg=
plain text
PS C:\Users\Megam\OneDrive\Documentos\NetBeansProjects\TestAes\target> java -cp .\TestAes-1.0-SNAPSHOT.jar com.mycompany.testaes.Program
wC6o7cUqZn9KS88L11OuNR2lGDcJ6zBrK1etJEpMHEg=
plain text
PS C:\Users\Megam\OneDrive\Documentos\NetBeansProjects\TestAes\target> java -cp .\TestAes-1.0-SNAPSHOT.jar com.mycompany.testaes.Program
gfM1uVf2a3x6Q/N0XhpDI4svUZx4kTmcl0wkjJfNQrw=
plain text
PS C:\Users\Megam\OneDrive\Documentos\NetBeansProjects\TestAes\target>
Dotnet
PS C:\Users\Megam\source\repos\ConsoleApplication1\ConsoleAppCs\bin\Debug\net5.0> .\ConsoleAppCs.exe
4GTqXhjkh0tXNI6Q4hShSdPPrKcWVEqA5LRBn6fBCH8=
plain text
PS C:\Users\Megam\source\repos\ConsoleApplication1\ConsoleAppCs\bin\Debug\net5.0> .\ConsoleAppCs.exe
aYY1sxre9KfLqkA1XtvN4IwGau6mYInmuvkopFXuKQA=
plain text
PS C:\Users\Megam\source\repos\ConsoleApplication1\ConsoleAppCs\bin\Debug\net5.0> .\ConsoleAppCs.exe
7lesPYAHQxdiCN4Cv5yWyWJlf5pqIukznZzpZTOOFeg=
plain text
PS C:\Users\Megam\source\repos\ConsoleApplication1\ConsoleAppCs\bin\Debug\net5.0>
I'm new to Android security concepts.
I have been reading some blogs to get to know about we can encrypt data using Public key and can decrypt it using respective Private key. Encryption seems to be doesn't have any problem, but when I try to decrypt it, it throws:
javax.crypto.BadPaddingException: error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02.
My code is as follows:
public String RSAEncrypt(final String plain, PublicKey publicKey ) throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte [] encryptedBytes = cipher.doFinal(plain.getBytes());
String encrypted = bytesToString(encryptedBytes);
System.out.println("EEncrypted?????" + encrypted );
return encrypted;
}
public String RSADecrypt(String encryptedBytes,PrivateKey privateKey ) throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException {
Cipher cipher1 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher1.init(Cipher.DECRYPT_MODE, privateKey);
byte [] decryptedBytes = cipher1.doFinal(stringToBytes(encryptedBytes));
String decrypted = new String(decryptedBytes);
System.out.println("DDecrypted?????" + decrypted);
return decrypted;
}
public String bytesToString(byte[] b) {
byte[] b2 = new byte[b.length + 1];
b2[0] = 1;
System.arraycopy(b, 0, b2, 1, b.length);
return new BigInteger(b2).toString(36);
}
public byte[] stringToBytes(String s) {
byte[] b2 = new BigInteger(s, 36).toByteArray();
return Arrays.copyOfRange(b2, 1, b2.length);
}
Stack trace is as follows:
07-28 11:27:35.119: I/System.out(22933): KEYSTORE : String to encrypt = > Hello
07-28 11:27:35.119: I/System.out(22933): KEYSTORE : [B#41bbf4d0
07-28 11:27:38.422: I/System.out(22933): KEYSTORE : String to Decrypt = > UJGAchuDhu3mqH5YPjmYqKBapJYMjJRk9g6HIy8bANooWorzwqgiEo+dOse6Nfq7i0yzw/Wt7TSdTNiYROxehkZvEx/mW5+Niw1CgZ2y9b/ijTeNTF+7aGPrqfDXJ38hUFdTPc6oNl2FVOIafncGOSK9po1JOAYeK0JiA2KrACfPLPjsLQSRzseThyYGxttRM7qbx/N0VTmlTeuNpLFld8Gtw3fHR8UoLGkH/OTFYPLZBVNE8t/oCCy8FpcCu9SGXxF8vh1R4rq15bfyyh9sBU9RuVtoLM0wDSbKixHhNOwwx2Z/A+SHDaQD9C+x3p1AnS9FYZm0Y07E+VYQWqzOpw
07-28 11:27:38.562: W/System.err(22933): javax.crypto.BadPaddingException: error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02
07-28 11:27:41.515: D/WifiNative-wlan0(773): doString: SIGNAL_POLL
07-28 11:27:41.515: W/WifiHW(773): QCOM Debug wifi_send_command "IFNAME=wlan0 SIGNAL_POLL"
07-28 11:27:41.525: D/wpa_supplicant(16189): nl80211: survey data missing!
07-2
07-28 11:27:56.612: W/WifiHW(773): QCOM Debug wifi_send_command "IFNAME=wlan0 SIGNAL_POLL"
07-28 11:27:56.612: D/wpa_supplicant(16189): nl80211: survey data missing!
07-28 11:27:56.622: I/wpa_supplicant(16189): environment dirty rate=0 [0][0][0]
07-28 11:27:56.622: D/WifiStateMachine(773): fetchRssiAndLinkSpeedNative RSSI = -62 abnormalRssiCnt = 0 newLinkSpeed = 58
07-28 11:27:56.622: D/WifiStateMachine(773): fetchRssiAndLinkSpeedNative mLinkspeedCount = 2, mLinkspeedSum: 116
I'm not sure where am going wrong.
A BadPaddingException occurs when the padding (bytes to fill up a too small encryption block) doesn't match a specified format (for example PKCS1, OAEP, ...). This can have a few causes:
You are using a different mode of RSA for en- and decryption.
The data (the byte[]) you get from encryption is not the same as the one you pass to decryption.
(You are using an incorrect KeyPair.)
Since you are initializing RSA with getInstance("RSA") for encryption and getInstance("RSA/ECB/PKCS1Padding") for decryption, it could be possible that ECB/PKCS1Padding is not the default on Android (even though it should be on Desktop-Java).
So try this in RSAEncrypt():
cipher.getInstance("RSA/ECB/PKCS1Padding");
If this does not work, make sure that you pass the exact same byte[] you get from cipher.doFinal() in encryption to cipher.doFinal() in decryption.
(Your code does work on my Desktop Java7 btw.)
you must break message to blocks.
can use below class.
// Note: RSA has block limitation, text size must < (SIZE/8) , otherwise you see [too much data for RSA block]
public class RSA
{
private RSAPublicKey internalPublicKey;
private RSAPrivateCrtKey internalPrivateKey;
private int SIZE = -1;
private String cipherAlgorithm = "RSA/None/PKCS1PADDING";
private String keyAlgorithm = "RSA";
private int b64State = Base64.NO_WRAP;
private static int b64State_static = Base64.NO_WRAP;
public RSA(int size)
{
SIZE = size;
init();
}
public RSA(int size, RSAPublicKey puk, RSAPrivateCrtKey prk)
{
if(puk == null)
throw new RuntimeException("Err: PublicKey is null.");
if(prk != null)
{
if(!puk.getModulus().equals(prk.getModulus()))
throw new RuntimeException("Err: PublicKey not matched by PrivateKey.");
}
SIZE = size;
internalPublicKey = puk;
internalPrivateKey = prk;
}
private void init()
{
try
{
//SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithSHA256And256BitAES-CBC-BC");
KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyAlgorithm);
kpg.initialize(SIZE); //initialize(SIZE, new SecureRandom());
KeyPair kp = kpg.genKeyPair();
internalPublicKey = (RSAPublicKey) kp.getPublic();
internalPrivateKey = (RSAPrivateCrtKey) kp.getPrivate();
}
catch(Exception e)
{throw new RuntimeException("Err: init RSA. " + e.toString());}
}
public int getSize()
{
return SIZE;
}
public RSAPublicKey getPublicKey()
{
return internalPublicKey;
}
public RSAPrivateCrtKey getPrivateKey()
{
return internalPrivateKey;
}
public String getPublicModule()
{
String s = internalPublicKey.toString();
return s.substring(s.indexOf("modulus")+8, s.indexOf(",publicExponent"));
}
public BigInteger getPublicModuleInt()
{
return internalPublicKey.getModulus();
}
public String getPublicExponent()
{
String s = internalPublicKey.toString();
return s.substring(s.indexOf("publicExponent")+15, s.lastIndexOf("}"));
}
public BigInteger getPublicExponentInt()
{
return internalPublicKey.getPublicExponent();
}
public String getPrivateExponent()
{
String s = internalPrivateKey.toString();
return s.substring(s.indexOf("privateExponent")+16, s.indexOf(",primeP"));
}
public String getPrimP()
{
String s = internalPrivateKey.toString();
return s.substring(s.indexOf("primeP=")+7, s.indexOf(",primeQ"));
}
public String getPrimQ()
{
String s = internalPrivateKey.toString();
return s.substring(s.indexOf("primeQ=")+7, s.indexOf(",primeExponentP"));
}
public String getPrimExponentP()
{
String s = internalPrivateKey.toString();
return s.substring(s.indexOf("primeExponentP=")+15, s.indexOf(",primeExponentQ"));
}
public String getPrimExponentQ()
{
String s = internalPrivateKey.toString();
return s.substring(s.indexOf("primeExponentQ=")+15, s.indexOf(",crtCoefficient"));
}
public String getCrtCoefficient()
{
String s = internalPrivateKey.toString();
return s.substring(s.indexOf("crtCoefficient=")+15, s.lastIndexOf(","));
}
public byte[] getPublicKeyAsByte()
{
return internalPublicKey.getEncoded();
}
public byte[] getPrivateKeyAsByte()
{
return internalPrivateKey.getEncoded();
}
public void changeCipherAlgorithm(String algorithm)
{
cipherAlgorithm = algorithm;
}
public byte[] getEncrypt(byte[] plain)
{
try
{
Cipher cipher = Cipher.getInstance(cipherAlgorithm);
cipher.init(Cipher.ENCRYPT_MODE, internalPublicKey);
return cipher.doFinal(plain);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(byte[] plain), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public byte[] getEncrypt(String plain)
{
try
{
return getEncrypt(plain.getBytes("UTF-8"));
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(String x), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public String getEncryptToB64(byte[] plain)
{
return Base64.encodeToString(getEncrypt(plain), b64State);
}
public byte[] getLargeEncrypt(byte[] plain, boolean byPadding) //byPadding = true if use RSA/xxx/xxxPADDING
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
try
{
int n = byPadding ? (getSize()/8) -11: (getSize()/8);
int offset = 0;
while(offset < plain.length)
{
byte[] section = Arrays.copyOfRange(plain, offset, Math.min(offset+n, plain.length));
byte[] cache = getEncrypt(section);
out.write(cache, 0, cache.length);
offset += n;
}
return out.toByteArray();
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getLargeEncrypt(String x), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public byte[] getLargeEncrypt(String plain, boolean byPadding) //byPadding = true if use RSA/xxx/xxxPADDING
{
return getLargeEncrypt(plain.getBytes(Charset.forName("UTF-8")), byPadding);
}
public String getLargeEncryptToB64(String plain, boolean byPadding) //byPadding = true if use RSA/xxx/xxxPADDING
{
return Base64.encodeToString(getLargeEncrypt(plain, byPadding), Base64.NO_WRAP);
}
public String getLargeEncryptToB64Block(String plain, boolean byPadding) //byPadding = true if use RSA/xxx/xxxPADDING
{
StringBuilder sb = new StringBuilder();
try
{
byte[] enc = plain.getBytes("UTF-8");
int n = byPadding ? (getSize()/8) -11: (getSize()/8);
int offset = 0;
while(offset < enc.length)
{
byte[] section = Arrays.copyOfRange(enc, offset, Math.min(offset+n, enc.length));
sb.append(getEncryptToB64(section));
offset += n;
}
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getLargeEncryptToB64Block(String x), ", Constants.DEFAULT_ALERT_STATE);
}
return sb.toString();
}
public String getLargeDecryptFromB64Block(String enc)
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
try
{
int n = (getSize()/8)-11;
int x = getEncryptToB64(TextHelper.generateString(n).getBytes("UTF-8")).length();
String[] ex = TextHelper.splitFix(enc, x);
for(int i=0; i<ex.length; i++)
{
byte[] sec = Base64.decode(ex[i], Base64.NO_WRAP);
out.write(sec, 0, sec.length);
//sb.append(getDecryptFromB64(ex[i]));
}
return getLargeDecryptToString(out.toByteArray());//sb.toString()
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getLargeDecryptFromB64Block(String x), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public byte[] getLargeDecrypt(byte[] enc)
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
try
{
int n = (getSize()/8);
int offset = 0;
while(offset < enc.length)
{
byte[] section = Arrays.copyOfRange(enc, offset, Math.min(offset+n, enc.length));
byte[] cache = getDecrypt(section);
out.write(cache, 0, cache.length);
offset += n;
}
return out.toByteArray();
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getLargeDecrypt(byte[] x), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public String getLargeDecryptToString(byte[] enc)
{
return new String(getLargeDecrypt(enc), Charset.forName("UTF-8"));
}
public String getLargeDecryptFromB64(String encB64)
{
return getLargeDecryptToString(Base64.decode(encB64, Base64.NO_WRAP));
}
public byte[] getDecrypt(byte[] encryptedBytes)
{
try
{
Cipher cipher = Cipher.getInstance(cipherAlgorithm);
cipher.init(Cipher.DECRYPT_MODE, internalPrivateKey);
return cipher.doFinal(encryptedBytes);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getDecrypt(byte[] x), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public String getDecryptFromB64(String encrypted)
{
try
{
byte[] b = Base64.decode(encrypted.getBytes("UTF-8"), b64State);
return getDecryptAsString(b);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getDecryptFromB64(String x), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public String getDecryptAsString(byte[] encryptedBytes)
{
return new String(getDecrypt(encryptedBytes), Charset.forName("UTF-8"));
}
public static byte[] getEncrypt(byte[] plain, PublicKey pk, Cipher cipher)
{
try
{
cipher.init(Cipher.ENCRYPT_MODE, pk);
return cipher.doFinal(plain);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(byte[] x, PublicKey pk, Cipher cipher), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static byte[] getEncrypt(String plain, PublicKey pk, Cipher cipher)
{
try
{
return getEncrypt(plain.getBytes("UTF-8"), pk, cipher);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(String x, PublicKey pk, Cipher cipher), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static byte[] getDecrypt(byte[] encryptedBytes, PrivateKey pk, Cipher cipher)
{
try
{
cipher.init(Cipher.DECRYPT_MODE, pk);
return cipher.doFinal(encryptedBytes);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static String getDecryptAsString(byte[] encryptedBytes, PrivateKey pk, Cipher cipher)
{
try
{
return new String(getDecrypt(encryptedBytes, pk, cipher), "UTF-8");
}
catch(Exception e){}
return null;
}
public static byte[] getDecrypt(final byte[] encryptedBytes, byte[] privateKey, Cipher cipher)
{
try
{
KeyFactory keyFac = KeyFactory.getInstance("RSA");
KeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
PrivateKey pk = keyFac.generatePrivate(keySpec);
cipher.init(Cipher.DECRYPT_MODE, pk);
return cipher.doFinal(encryptedBytes);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static String getDecryptAsString(final byte[] encryptedBytes, byte[] privateKey, Cipher cipher)
{
return new String(getDecrypt(encryptedBytes, privateKey, cipher), Charset.forName("UTF-8"));
}
public static byte[] sign(byte[] forSign, PrivateKey byThisKey)
{
try
{
Signature privateSignature = Signature.getInstance("SHA1withRSA");//or SHA256withRSA
privateSignature.initSign(byThisKey);
privateSignature.update(forSign);
return privateSignature.sign();
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: sign(), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static String sign(String forSign, PrivateKey byThisKey)
{
return Base64.encodeToString(sign(forSign.getBytes(), byThisKey), b64State_static);
}
public static boolean verify(String plainText, String signature, PublicKey publicKey)
{
Signature publicSignature;
try
{
publicSignature = Signature.getInstance("SHA1withRSA");
publicSignature.initVerify(publicKey);
publicSignature.update(plainText.getBytes());
byte[] signatureBytes = Base64.decode(signature, b64State_static);
return publicSignature.verify(signatureBytes);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: verify(), ", Constants.DEFAULT_ALERT_STATE);
}
return false;
}
public static RSAPublicKey generatePublicKey(String modulus, String exponent)
{
try
{
BigInteger modBigInteger = new BigInteger(modulus, 16);
BigInteger exBigInteger = new BigInteger(exponent, 16);
RSAPublicKeySpec spec = new RSAPublicKeySpec(modBigInteger, exBigInteger);
KeyFactory factory = KeyFactory.getInstance("RSA");
return (RSAPublicKey) factory.generatePublic(spec);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static RSAPublicKey generatePublicKey(BigInteger modulus, BigInteger exponent)
{
try
{
RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent);
KeyFactory factory = KeyFactory.getInstance("RSA");
return (RSAPublicKey) factory.generatePublic(spec);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getEncrypt(), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static RSAPublicKey generatePublicKeyFromDotNet(String modulus, String exponent)
{
return generatePublicKey(RSA.parseDotNetBigInt(modulus), RSA.parseDotNetBigInt(exponent));
}
public static RSAPrivateCrtKey generatePrivateKeyFromDotNet(String modulus, String pubEx, String priEx, String p, String q, String dp, String dq,String invQ)
{
return generatePrivateKey(RSA.parseDotNetBigInt(modulus), RSA.parseDotNetBigInt(pubEx), RSA.parseDotNetBigInt(priEx), RSA.parseDotNetBigInt(p)
,RSA.parseDotNetBigInt(q),RSA.parseDotNetBigInt(dp), RSA.parseDotNetBigInt(dq), RSA.parseDotNetBigInt(invQ));
}
public static PublicKey generateBCPublicKey(String modulus, String exponent)
{
try
{
BigInteger modBigInteger = new BigInteger(modulus, 16);
BigInteger exBigInteger = new BigInteger(exponent, 16);
RSAPublicKeySpec spec = new RSAPublicKeySpec(modBigInteger, exBigInteger);
KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
return factory.generatePublic(spec);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: getBCPublicKey(), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static RSAPrivateCrtKey generatePrivateKey(String modulus, String publicExpo, String privateExpo, String primP, String primQ, String ePrimP, String ePrimQ, String cof)
{
try
{
BigInteger module = new BigInteger(modulus, 16);
BigInteger expo1 = new BigInteger(publicExpo, 16);
BigInteger expo2 = new BigInteger(privateExpo, 16);
BigInteger prim_P = new BigInteger(primP, 16);
BigInteger prim_Q = new BigInteger(primQ, 16);
BigInteger prim_EP = new BigInteger(ePrimP, 16);
BigInteger prim_EQ = new BigInteger(ePrimQ, 16);
BigInteger coefficient = new BigInteger(cof, 16);
/*BigInteger module = new BigInteger(1, Base64.encode(modulus.getBytes(), b64State));*/
RSAPrivateCrtKeySpec spec = new RSAPrivateCrtKeySpec(module, expo1, expo2, prim_P, prim_Q, prim_EP, prim_EQ, coefficient);
KeyFactory factory = KeyFactory.getInstance("RSA");
return (RSAPrivateCrtKey) factory.generatePrivate(spec);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static RSAPrivateCrtKey generatePrivateKey(BigInteger modulus, BigInteger publicExpo, BigInteger privateExpo, BigInteger primP, BigInteger primQ, BigInteger ePrimP, BigInteger ePrimQ, BigInteger cof)
{
try
{
RSAPrivateCrtKeySpec spec = new RSAPrivateCrtKeySpec(modulus, publicExpo, privateExpo, primP, primQ, ePrimP, ePrimQ, cof);
KeyFactory factory = KeyFactory.getInstance("RSA");
return (RSAPrivateCrtKey) factory.generatePrivate(spec);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static PrivateKey generateBCPrivateKey(String modulus, String publicExpo, String privateExpo, String primP, String primQ, String ePrimP, String ePrimQ, String cof)
{
try
{
BigInteger module = new BigInteger(modulus, 16);
BigInteger expo1 = new BigInteger(publicExpo, 16);
BigInteger expo2 = new BigInteger(privateExpo, 16);
BigInteger prim_P = new BigInteger(primP, 16);
BigInteger prim_Q = new BigInteger(primQ, 16);
BigInteger prim_EP = new BigInteger(ePrimP, 16);
BigInteger prim_EQ = new BigInteger(ePrimQ, 16);
BigInteger coefficient = new BigInteger(cof, 16);
RSAPrivateCrtKeySpec spec = new RSAPrivateCrtKeySpec(module, expo1, expo2, prim_P, prim_Q, prim_EP, prim_EQ, coefficient);
KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
return factory.generatePrivate(spec);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static Cipher generateCipher(String alg,#Nullable String provider)
{
try
{
if(provider == null)
return Cipher.getInstance(alg);
else
return Cipher.getInstance(alg, provider);
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: generateCipher(), ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static BigInteger parseDotNetBigInt(String b64BigInt)
{
try
{
String modulusHex = Hex.encodeHex(Base64.decode(b64BigInt.getBytes("UTF-8"), Base64.NO_WRAP));
return new BigInteger(modulusHex, 16);
}
catch (Exception ex)
{
ThreadHelper.exceptionAlert(ex, Constants.TAG_FOR_LOG, "Err: parseDotNetBigInt(),", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static String privateKeyToXMLString(RSAPrivateCrtKey key)
{
try
{
Document xml = privateKeyToXML(key);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
StringWriter sw = new StringWriter();
transformer.transform(new DOMSource(xml), new StreamResult(sw));
return sw.getBuffer().toString();
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: privateKeyToXMLString(RSAPrivateCrtKey x),", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static String publicKeyToXMLString(RSAPublicKey key)
{
try
{
Document xml = publicKeyToXML(key);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
StringWriter sw = new StringWriter();
transformer.transform(new DOMSource(xml), new StreamResult(sw));
return sw.getBuffer().toString();
}
catch(Exception e){}
return null;
}
public static Document publicKeyToXML(RSAPublicKey key)
{
try
{
Document result = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element rsaKeyValue = result.createElement("RSAKeyValue");
result.appendChild(rsaKeyValue);
Element modulus = result.createElement("Modulus");
rsaKeyValue.appendChild(modulus);
byte[] modulusBytes = key.getModulus().toByteArray();
modulusBytes = stripLeadingZeros(modulusBytes);
modulus.appendChild(result.createTextNode(new String(Base64.encode(modulusBytes, b64State_static))));
Element exponent = result.createElement("Exponent");
rsaKeyValue.appendChild(exponent);
byte[] exponentBytes = key.getPublicExponent().toByteArray();
exponent.appendChild(result.createTextNode(new String(Base64.encode(exponentBytes, b64State_static))));
return result;
}
catch(Exception e){}
return null;
}
public static Document privateKeyToXML(RSAPrivateCrtKey key)
{
try
{
Document result = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element rsaKeyValue = result.createElement("RSAKeyValue");
result.appendChild(rsaKeyValue);
Element modulus = result.createElement("Modulus");
rsaKeyValue.appendChild(modulus);
Element exponent = result.createElement("Exponent");
rsaKeyValue.appendChild(exponent);
Element P = result.createElement("P");
rsaKeyValue.appendChild(P);
Element Q = result.createElement("Q");
rsaKeyValue.appendChild(Q);
Element DP = result.createElement("DP");
rsaKeyValue.appendChild(DP);
Element DQ = result.createElement("DQ");
rsaKeyValue.appendChild(DQ);
Element InverseQ = result.createElement("InverseQ");
rsaKeyValue.appendChild(InverseQ);
Element D = result.createElement("D");
rsaKeyValue.appendChild(D);
byte[] modulusBytes = key.getModulus().toByteArray();
modulusBytes = stripLeadingZeros(modulusBytes);
modulus.appendChild(result.createTextNode(new String(Base64.encode(modulusBytes, b64State_static))));
byte[] pubExponent = key.getPublicExponent().toByteArray();
exponent.appendChild(result.createTextNode(new String(Base64.encode(pubExponent, b64State_static))));
byte[] p = key.getPrimeP().toByteArray();
P.appendChild(result.createTextNode(new String(Base64.encode(p, b64State_static))));
byte[] q = key.getPrimeQ().toByteArray();
Q.appendChild(result.createTextNode(new String(Base64.encode(q, b64State_static))));
byte[] ep = key.getPrimeExponentP().toByteArray();
DP.appendChild(result.createTextNode(new String(Base64.encode(ep, b64State_static))));
byte[] eq = key.getPrimeExponentP().toByteArray();
DQ.appendChild(result.createTextNode(new String(Base64.encode(eq, b64State_static))));
byte[] cof = key.getCrtCoefficient().toByteArray();
InverseQ.appendChild(result.createTextNode(new String(Base64.encode(cof, b64State_static))));
byte[] priExponent = key.getPrivateExponent().toByteArray();
D.appendChild(result.createTextNode(new String(Base64.encode(priExponent, b64State_static))));
return result;
}
catch(Exception e)
{
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static byte[] stripLeadingZeros(byte[] input)
{
while (input[0] == (byte) 0)
{
input = Arrays.copyOfRange(input, 1, input.length);
}
return input;
}
public static void saveKey(File file, PublicKey key)
{
try
{
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key.getEncoded());
FileOutputStream fos = new FileOutputStream(file);
fos.write(x509EncodedKeySpec.getEncoded());
fos.close();
}
catch(Exception e){}
}
public static void saveKey(File file, PrivateKey key)
{
try
{
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key.getEncoded());
FileOutputStream fos = new FileOutputStream(file);
fos.write(pkcs8EncodedKeySpec.getEncoded());
fos.close();
}
catch(Exception e){}
}
public PublicKey openPublicKey(String path, String algorithm)
{
try
{
File filePublicKey = new File(path);
FileInputStream fis = new FileInputStream(path);
byte[] encodedPublicKey = new byte[(int) filePublicKey.length()];
fis.read(encodedPublicKey);
fis.close();
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey);
return keyFactory.generatePublic(publicKeySpec);
}
catch(Exception e){}
return null;
}
public PrivateKey openPrivateKey(String path, String algorithm)
{
try
{
File filePrivateKey = new File(path);
FileInputStream fis = new FileInputStream(path);
byte[] encodedPrivateKey = new byte[(int) filePrivateKey.length()];
fis.read(encodedPrivateKey);
fis.close();
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);//RSA
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
return keyFactory.generatePrivate(privateKeySpec);
}
catch(Exception e){}
return null;
}
public static RSAPublicKey fetchPublicKeyFromXML(Document xml)
{
try
{
Element root = XMLMaster.getRoot(xml);
String mud = XMLMaster.getTextContent(root, "Modulus", 0);
String pubE = XMLMaster.getNodeValue(root, "Exponent", 0);
return generatePublicKeyFromDotNet(mud, pubE);
}
catch (Throwable e)
{
//throw new RuntimeException("Err: can not fetch PublicKey. " + e.toString());
ThreadHelper.exceptionAlert(e, Constants.TAG_FOR_LOG, "Err: can not fetch PublicKey. ", Constants.DEFAULT_ALERT_STATE);
}
return null;
}
public static RSAPrivateCrtKey fetchPrivateKeyFromXML(Document xml)
{
try
{
Element root = XMLMaster.getRoot(xml);
String mud = XMLMaster.getTextContent(root, "Modulus", 0);
String pubE = XMLMaster.getNodeValue(root, "Exponent", 0);
String priE = XMLMaster.getNodeValue(root, "D", 0);
String p = XMLMaster.getNodeValue(root, "P", 0);
String Q = XMLMaster.getNodeValue(root, "Q", 0);
String EP = XMLMaster.getNodeValue(root, "DP", 0);
String EQ = XMLMaster.getNodeValue(root, "DQ", 0);
String cof = XMLMaster.getNodeValue(root, "InverseQ", 0);
return generatePrivateKeyFromDotNet(mud, pubE, priE, p, Q, EP, EQ, cof);
}
catch (Throwable e)
{
throw new RuntimeException("Err: can not fetch PrivateKey. " + e.toString());
}
}
public static PrivateKey loadPrivateKey(String privateKeyB64)
{
try
{
byte[] buffer = Base64.decode(privateKeyB64, Base64.NO_WRAP);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePrivate(keySpec);
//Class c = Reflector.getClassByAddressName("com.android.org.conscrypt.OpenSSLRSAPrivateKey");
//RSAPrivateKeySpec privSpec = new RSAPrivateKeySpec(modules, d);
}
catch (Throwable e)
{
throw new RuntimeException("Err: can not load PrivateKey. " + e.toString());
}
}
public String convertCaseToString(BigInteger num)
{
return num.toString(16);
} // Use: convertCaseToString(rsa.getPublicModule())
}
Because you are working with encrypted data, it is unlikely you can convert that directly to a String (each byte may not correspond to a character store-able in a String) - therefore I'd expect bytesToString(encryptedBytes) to usually fail. Try converting the encrypted data to Base64 first then that will always be store-able in a String. You then simply do the reverse to decrypt:-
// to encrypt and get a String object
byte[] encode = Base64.encode(encryptedBytes, Base64.NO_PADDING|Base64.NO_WRAP);
String encryptedDataStr = new String(encode);
Then you can do stuff (like store) the encryptedDataStr or whaterver. Then later...
// to decrypt
byte[] encryptedBytes = Base64.decode(encryptedDataStr, Base64.NO_PADDING|Base64.NO_WRAP);
byte [] decryptedBytes = cipher1.doFinal(encryptedBytes);
Good luck!