How to use RSA between Go and Android - android

I (1) create Public key in Go and send it for Android
(2) android use below code to Encrypt it's data to send to Go with string type
(3) Go get string data and try to Decrypt it, but it can't.
My Go code:
// DecryptWithPrivateKey decrypts data with private key
func DecryptWithPrivateKey(ciphertext []byte, priv *rsa.PrivateKey) []byte {
plaintext, err := rsa.DecryptPKCS1v15(rand.Reader, priv , ciphertext)
if err != nil {
log.Println(err)
}
return plaintext
}
.
.
.
so.On("serverpublic", func(msg string) {
mes := []byte(msg)
decbyte :=DecryptWithPrivateKey(data,pr)
str := fmt.Sprintf("%s", decbyte)
log.Println("encript data from Android ---->" , str)
})
Android studio code:
public final static String chi="RSA/NONE/PKCS1Padding"; //RSA/ECB/PKCS1Padding
private static byte[] dec4golang(byte[] src) throws Exception {
Cipher cipher = Cipher.getInstance(chi);
cipher.init(Cipher.DECRYPT_MODE, serverrk);
return cipher.doFinal(src);
}
private static byte[] enc4golang(String text, PublicKey pubRSA) throws Exception{
Cipher cipher = Cipher.getInstance(chi);
cipher.init(Cipher.ENCRYPT_MODE, pubRSA);
return cipher.doFinal(text.getBytes("UTF-8")); //i also advice you to use: .getBytes("UTF-8"); instead of data.getBytes();
}
public final static String enc4golang(String text){
try {
return byte2hex(enc4golang(text, serveruk));
// return enc4golang(text, serveruk).toString();
// return new String(enc4golang(text, serveruk), "UTF-8");
// return new String(enc4golang(text, serveruk), Charset.forName("utf-8"));
// return Base64.encodeToString(enc4golang(text, serveruk), Base64.DEFAULT);///nodejs
// return Base64Utils.encodeToString(enc4golang(text, serveruk));
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
public static String byte2hex(byte[] b)
{
String hs = "";
String stmp = "";
for (int n = 0; n < b.length; n ++)
{
stmp = Integer.toHexString(b[n] & 0xFF);
if (stmp.length() == 1)
hs += ("0" + stmp);
else
hs += stmp;
}
return hs.toUpperCase();
}
I think my problem is in these lines:
chi="RSA/NONE/PKCS1Padding"; //RSA/ECB/PKCS1Padding
OR
return byte2hex(enc4golang(text, serveruk));

I have tested it and it worked.
in Go i use this fnction:
func rusdec(encryptedString string , privateKey string) (string, error) {
base64DecodeBytes, err := base64.StdEncoding.DecodeString(encryptedString)
if err != nil {
return "", err
}
privateKeyBlock, _ := pem.Decode([]byte(privateKey))
var pri *rsa.PrivateKey
pri, parseErr := x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
if parseErr != nil {
return "", parseErr
}
decryptedData, decryptErr := rsa.DecryptOAEP(sha1.New(), rand.Reader, pri, base64DecodeBytes, nil)
if decryptErr != nil {
return "", decryptErr
}
return string(decryptedData), nil
}
and in Android studio :
public final static String chi="RSA/ECB/OAEPPadding";
public final static String RSA = "RSA";
private final static int CRYPTO_BITS = 512;
public static PublicKey stringToPublicKeytoserver(String publicKeyString)
{
try {
if (publicKeyString.contains("-----BEGIN PUBLIC KEY-----") || publicKeyString.contains("-----END PUBLIC KEY-----"))
publicKeyString = publicKeyString.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "");
publicKeyString = publicKeyString.replace("-----BEGIN PUBLIC KEY-----", "");
publicKeyString = publicKeyString.replace("-----END PUBLIC KEY-----", "");
byte[] keyBytes = Base64.decode(publicKeyString, Base64.DEFAULT);
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
serveruk=keyFactory.generatePublic(spec);
return serveruk;
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
e.printStackTrace();
return null;
}
}
private static byte[] enc4golang(String text, PublicKey pubRSA) throws Exception{
Cipher cipher = Cipher.getInstance(chi);
cipher.init(Cipher.ENCRYPT_MODE, pubRSA);
return cipher.doFinal(text.getBytes("UTF-8")); //i also advice you to use: .getBytes("UTF-8"); instead of data.getBytes();
}
public final static String enc4golang(String text){
try {
return Base64.encodeToString(enc4golang(text, serveruk) ,Base64.DEFAULT); //send this string to golang
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
public and private Key for Go:
const priPEM = `-----BEGIN RSA PRIVATE KEY-----
MIIBOQIBAAJBALEZ+CmY7YN7KWib5Oh0AuWqfHiq3aURV1WGaaBm+X43kF3RRGJd
HbVdOEb2+YoNyni+LD5CQ4R3T7/f0sePzv0CAwEAAQJAc0MAlSoXotPcjl2vrG4c
mJbNrcceu9i+a0Ywppl+VVsEPOnapMQsVM04BpJzFmi00S+Sxl0pO1oAX0pwX7Oq
4QIhAOcncV+SQYlOWoH/phOGkA3y5j0eO2uUfqrXJX0q6/+FAiEAxCMvlkSePzkn
EROwzJu8tpZrIB6CNZ5KKfhPW7Dj3xkCIEvW1w2iMLpZ6LwKInT5iz3oWb3ns1si
h0SJ/hTJBlD5AiAKEtyQ1TljeeX9xIsiFyWcIyGhZq+9XUHl4fEBfpZVkQIgMfrj
qLoCdQH1D5F69WUMYd0n36Xpmqf7L9yV0Ofkz1Y=
-----END RSA PRIVATE KEY-----`
const pubPEM = `-----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALEZ+CmY7YN7KWib5Oh0AuWqfHiq3aUR
V1WGaaBm+X43kF3RRGJdHbVdOEb2+YoNyni+LD5CQ4R3T7/f0sePzv0CAwEAAQ==
-----END PUBLIC KEY-----`

Related

building encryption SHA 1 from Parameter for android to json parse

I have problem with build Encryption from String to SHA 1 encrypt maybe in here can help me
This my Parameter
String AgentID = "7001";
String AgentPIN = "68820025";
String ScreetKey = "63e3cd0a";
String AgentTrxID = "201802090013";
String AgentStoreID = "01010101";
String pdam = pdam1;
String CustomerID =
edit_nomorpelangganpdam.getText().toString().trim();
String DateTimeRequest = (String)
DateFormat.format("yyyyMMddHHmmss", new Date());
And this my code for SHA 1
StringBuilder buf = new StringBuilder();
for (byte b : data) {
int halfbyte = (b >>> 4) & 0x0;
int two_halfs = 0;
do {
buf.append((0 <= halfbyte) && (halfbyte <= 9) ? (char) ('0' + halfbyte) : (char) ('a' + (halfbyte - 10)));
halfbyte = b & 0x0F;
} while (two_halfs++ < 1);
}
return buf.toString();
}
public static String SHA1(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(text.getBytes("UTF-8"), 0, text.length());
byte[] sha1hash = md.digest();
return convertToHex(sha1hash);
}
I want to make like this Encryption
93d97a890c312a7f33ca2c393ec070a7e1b42cdc
Please try this code
// Call this method where you wont
encryptString("Your String value")
private static String encryptString(String value)
{
String sha1 = "";
try
{
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(value.getBytes("UTF-8"));
sha1 = byteToHexadecimal(crypt.digest());
}
catch(NoSuchAlgorithmException e)
{
e.printStackTrace();
}
catch(UnsupportedEncodingException e)
{
e.printStackTrace();
}
return sha1;
}
private static String byteToHexadecimal(final byte[] hash)
{
Formatter formatter = new Formatter();
for (byte b : hash)
{
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}

Triple DES Algorithm in Android JAVA

I am new to Android-Java. I have below function in C# for Encryption (Triple DES)
public string Encrypt(string data)
{
try
{
if (!string.IsNullOrEmpty(data))
{
//byte[] keyArray;
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(data);
//System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader();
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
TripleDESCryptoServiceProvider CryptDesECB = new TripleDESCryptoServiceProvider();
CryptDesECB.Key = keyArray;
CryptDesECB.Mode = CipherMode.ECB;
CryptDesECB.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = CryptDesECB.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
CryptDesECB.Clear();
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
return string.Empty;
}
catch (Exception)
{
return string.Empty;
}
}
I have tried below code for having same Encryption function in Android platform:
public static String EncryptText(String message) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] digestOfPassword = md.digest(secretKey.getBytes("utf-8"));
byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
SecretKey key = new SecretKeySpec(keyBytes, "DESede");
Cipher cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] plainTextBytes = message.getBytes("utf-8");
byte[] buf = cipher.doFinal(plainTextBytes);
byte [] base64Bytes = Base64.encode(buf,Base64.DEFAULT);
String base64EncryptedString = new String(base64Bytes);
return base64EncryptedString;
}
But, the encryption result is different on both platforms? If anyone can help me in pointing the issue in Android function.
Thanks in advance.
I wrote below class for Triple DES ECB mode PKCS5/7 padding mode encryption-decryption and it worked for me:
public class DESedeEncryption {
private static final String UNICODE_FORMAT = "UTF8";
public static final String DESEDE_ENCRYPTION_SCHEME = "DESede";
private KeySpec myKeySpec;
private SecretKeyFactory mySecretKeyFactory;
private Cipher cipher;
byte[] keyAsBytes;
private String myEncryptionKey;
private String myEncryptionScheme;
SecretKey key;
public DESedeEncryption() throws Exception
{
myEncryptionKey = "YOURPRIVATEKEY";
myEncryptionScheme = DESEDE_ENCRYPTION_SCHEME;
keyAsBytes = myEncryptionKey.getBytes(UNICODE_FORMAT);
myKeySpec = new DESedeKeySpec(keyAsBytes);
mySecretKeyFactory = SecretKeyFactory.getInstance(myEncryptionScheme);
cipher = Cipher.getInstance(myEncryptionScheme);
key = mySecretKeyFactory.generateSecret(myKeySpec);
}
/**
* Method To Encrypt The String
*/
public String encrypt(String unencryptedString) {
String encryptedString = null;
try {
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] plainText = unencryptedString.getBytes(UNICODE_FORMAT);
byte[] encryptedText = cipher.doFinal(plainText);
encryptedString = Base64.encodeToString(encryptedText, Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
}
return encryptedString.endsWith("\n") ? encryptedString.replace("\n","") : encryptedString;
}
/**
* Method To Decrypt An Ecrypted String
*/
public String decrypt(String encryptedString) {
String decryptedText=null;
try {
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] encryptedText = Base64.decode(encryptedString, Base64.DEFAULT);
byte[] plainText = cipher.doFinal(encryptedText);
decryptedText= bytes2String(plainText);
} catch (Exception e) {
e.printStackTrace();
}
return decryptedText;
}
/**
* Returns String From An Array Of Bytes
*/
private static String bytes2String(byte[] bytes) {
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i > bytes.length; i++) {
stringBuffer.append((char) bytes[i]);
}
return stringBuffer.toString();
}
}

Cipher functions:EVP_DecryptFinal_ex:DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH

Im trying to implement AES in an Android application. The server is a PHP server.
This is the AES code :
public class AES{
private String SecretKey = "89432hjfsd891787";
private String iv = "fedcba9876543210";
private IvParameterSpec ivspec;
private SecretKeySpec keyspec;
private Cipher cipher;
public AES()
{
ivspec = new IvParameterSpec(iv.getBytes());
keyspec = new SecretKeySpec(SecretKey.getBytes(), "AES");
try {
cipher = Cipher.getInstance("AES/CBC/NoPadding");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public byte[] encrypt(String text) throws Exception
{
if(text == null || text.length() == 0)
throw new Exception("Empty string");
byte[] encrypted = null;
try {
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
encrypted = cipher.doFinal(padString(text).getBytes());
} catch (Exception e)
{
throw new Exception("[encrypt] " + e.getMessage());
}
return encrypted;
}
public byte[] decrypt(String code) throws Exception
{
if(code == null || code.length() == 0)
throw new Exception("Empty string");
byte[] decrypted = null;
try {
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
decrypted = cipher.doFinal(hexToBytes(code));
} catch (Exception e)
{
throw new Exception("[decrypt] " + e.getMessage());
}
return decrypted;
}
public static String bytesToHex(byte[] data)
{
if (data==null)
{
return null;
}
int len = data.length;
String str = "";
for (int i=0; i<len; i++) {
if ((data[i]&0xFF)<16)
str = str + "0" + java.lang.Integer.toHexString(data[i]&0xFF);
else
str = str + java.lang.Integer.toHexString(data[i]&0xFF);
}
return str;
}
public static byte[] hexToBytes(String str) {
if (str==null) {
return null;
} else if (str.length() < 2) {
return null;
} else {
int len = str.length() / 2;
byte[] buffer = new byte[len];
for (int i=0; i<len; i++) {
buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16);
}
return buffer;
}
}
private static String padString(String source)
{
char paddingChar = ' ';
int size = 16;
int x = source.length() % size;
int padLength = size - x;
for (int i = 0; i < padLength; i++) {
source += paddingChar;
}
return source;
}
}
I get an error while decrypting the incoming string : Cipher functions:EVP_DecryptFinal_ex:DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH
How do i go about this?
Manually padding the String representation of the plaintext with spaces is not a good padding mechanism. Instead, you should use AES/CBC/PKCS5Padding which will handle the padding as prescribed in PKCS #5/#7.
You should also:
generate a unique IV per encryption operation rather than re-using the same value for all messages
Use an authenticated mode of operation (GCM, HMAC/SHA-256 MAC over cipher text, etc.)
Store the key in hexadecimal representation of the raw bytes rather than an ASCII/UTF-8 String encoding (not specified in your code)
Encode the cipher text in Base64 or Hex before serializing/transmitting. Encoding errors can contribute to padding exceptions during decryption.

Converting a string sent via SMS into RSA Public/Private key in android

I've been working on it for several days but without success, I' m doing SMS encryption in android using RSA encryption, the problem is how can I convert a String to public key and use it for encryption, I'm sending the publicKey converted into String via SMS but I'm not able to get the key back.
This is how my algorithm works but when I send "puk" as a string via Sms and make encryption it doesn't work anymore!!! plz help me . . .
private final static String RSA = "RSA";
public static PublicKey uk;
public static PrivateKey rk;
public static String puk;
public static void generateKey() throws Exception
{
KeyPairGenerator gen = KeyPairGenerator.getInstance(RSA);
gen.initialize(128, new SecureRandom());
KeyPair keyPair = gen.generateKeyPair();
uk = keyPair.getPublic();
rk = keyPair.getPrivate();
puk = uk.toString();
}
private static byte[] encrypt(String text, PublicKey pubRSA) throws Exception
{
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.ENCRYPT_MODE, pubRSA);
return cipher.doFinal(text.getBytes());
}
public final static String encrypt(String text)
{
try {
return byte2hex(encrypt(text, uk));
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
public final static String decrypt(String data)
{
try{
String text = new String(decrypt(hex2byte(data.getBytes())));
return text+" OK";
}
catch (Exception e)
{
return "Error: "+e;
}
}
private static byte[] decrypt(byte[] src) throws Exception
{
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.DECRYPT_MODE, rk);
return cipher.doFinal(src);
}
public static String byte2hex(byte[] b)
{
String hs = "";
String stmp = "";
for (int n = 0; n < b.length; n ++)
{
stmp = Integer.toHexString(b[n] & 0xFF);
if (stmp.length() == 1)
hs += ("0" + stmp);
else
hs += stmp;
}
return hs.toUpperCase();
}
public static byte[] hex2byte(byte[] b)
{
if ((b.length % 2) != 0)
throw new IllegalArgumentException("hello");
byte[] b2 = new byte[b.length / 2];
for (int n = 0; n < b.length; n += 2)
{
String item = new String(b, n, 2);
b2[n/2] = (byte)Integer.parseInt(item, 16);
}
return b2;
}

Exception - Illegal Block size during decryption(Android)

I am writing an application which encrypts and decrypts the user notes based on the user set password. i used the following algorithms for encryption/decryption
1. PBEWithSHA256And256BitAES-CBC-BC
2. PBEWithMD5And128BitAES-CBC-OpenSSL
e_Cipher = Cipher.getInstance(PBEWithSHA256And256BitAES-CBC-BC);
d_Cipher = Cipher.getInstance(PBEWithSHA256And256BitAES-CBC-BC);
e_Cipher.init()
d_Cipher.init()
encryption is working well, but when trying to decrypt it gives
Exception - Illegal Block size
after encryption i am converting the cipherText to HEX and storing it in a sqlite database. i am retrieving correct values from the sqlite database during decyption but when calling d_Cipher.dofinal() it throws the Exception.
I thought i missed to specify the padding and tried to check what are the other available cipher algorithms but i was unable to found.
so request you to please give the some knowledge on what are the cipher algorithms and padding that are supported by Android? if the algorithm which i used can be used for padding, how should i specify the padding mechanism?
I am pretty new to Encryption so tried a couple of algorithms which are available in BouncyCastle.java but unsuccessful.
As requested here is the code
public class CryptoHelper {
private static final String TAG = "CryptoHelper";
//private static final String PBEWithSHA256And256BitAES = "PBEWithSHA256And256BitAES-CBC-BC";
//private static final String PBEWithSHA256And256BitAES = "PBEWithMD5And128BitAES-CBC-OpenSSL";
private static final String PBEWithSHA256And256BitAES = "PBEWithMD5And128BitAES-CBC-OpenSSLPBEWITHSHA1AND3-KEYTRIPLEDES-CB";
private static final String randomAlgorithm = "SHA1PRNG";
public static final int SALT_LENGTH = 8;
public static final int SALT_GEN_ITER_COUNT = 20;
private final static String HEX = "0123456789ABCDEF";
private Cipher e_Cipher;
private Cipher d_Cipher;
private SecretKey secretKey;
private byte salt[];
public CryptoHelper(String password) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeySpecException {
char[] cPassword = password.toCharArray();
PBEKeySpec pbeKeySpec = new PBEKeySpec(cPassword);
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, SALT_GEN_ITER_COUNT);
SecretKeyFactory keyFac = SecretKeyFactory.getInstance(PBEWithSHA256And256BitAES);
secretKey = keyFac.generateSecret(pbeKeySpec);
SecureRandom saltGen = SecureRandom.getInstance(randomAlgorithm);
this.salt = new byte[SALT_LENGTH];
saltGen.nextBytes(this.salt);
e_Cipher = Cipher.getInstance(PBEWithSHA256And256BitAES);
d_Cipher = Cipher.getInstance(PBEWithSHA256And256BitAES);
e_Cipher.init(Cipher.ENCRYPT_MODE, secretKey, pbeParamSpec);
d_Cipher.init(Cipher.DECRYPT_MODE, secretKey, pbeParamSpec);
}
public String encrypt(String cleartext) throws IllegalBlockSizeException, BadPaddingException {
byte[] encrypted = e_Cipher.doFinal(cleartext.getBytes());
return convertByteArrayToHex(encrypted);
}
public String decrypt(String cipherString) throws IllegalBlockSizeException {
byte[] plainText = decrypt(convertStringtobyte(cipherString));
return(new String(plainText));
}
public byte[] decrypt(byte[] ciphertext) throws IllegalBlockSizeException {
byte[] retVal = {(byte)0x00};
try {
retVal = d_Cipher.doFinal(ciphertext);
} catch (BadPaddingException e) {
Log.e(TAG, e.toString());
}
return retVal;
}
public String convertByteArrayToHex(byte[] buf) {
if (buf == null)
return "";
StringBuffer result = new StringBuffer(2*buf.length);
for (int i = 0; i < buf.length; i++) {
appendHex(result, buf[i]);
}
return result.toString();
}
private static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
}
private static byte[] convertStringtobyte(String hexString) {
int len = hexString.length()/2;
byte[] result = new byte[len];
for (int i = 0; i < len; i++) {
result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
}
return result;
}
public byte[] getSalt() {
return salt;
}
public SecretKey getSecretKey() {
return secretKey;
}
public static SecretKey createSecretKey(char[] password) throws NoSuchAlgorithmException, InvalidKeySpecException {
PBEKeySpec pbeKeySpec = new PBEKeySpec(password);
SecretKeyFactory keyFac = SecretKeyFactory.getInstance(PBEWithSHA256And256BitAES);
return keyFac.generateSecret(pbeKeySpec);
}
}
I will call mCryptoHelper.decrypt(String str) then this results in Illegal block size exception
My Env: Android 1.6 on Eclipse
#Vamsi is correct, it looks like a new Salt is being generated. This should be generated once, and stored as a known to the program. If the salt changes, then the encrypt/decrypt data checks aren't going to match.
In the code, each time i am generating the "salt",
SecureRandom saltGen = SecureRandom.getInstance(randomAlgorithm);
this.salt = new byte[SALT_LENGTH];
saltGen.nextBytes(this.salt);
hence there is a difference between the encryption and decryption cipher. so it is giving the error Bad Pad block or Padding block corrupted.
If i declare the Salt to some known value, it is working fine.

Categories

Resources