I want to encrypt data from a client and send it to a server over a socket. The client is written in Java and the server is written in C. However, the result is not the same as my expected.
The C program as follows:
#define MAX_BUFF 1024
#define MAX_LENGTH_DATA 1024
static void decrypt128(unsigned char intput[], unsigned char output[]) {
mbedtls_aes_context context_out;
unsigned char key1[] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P'};
unsigned char iv1[16] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P' };
unsigned char decrypt[128];
mbedtls_aes_init(&context_out);
mbedtls_aes_setkey_dec(&context_out, key1, 128);
mbedtls_aes_crypt_cbc(&context_out, MBEDTLS_AES_DECRYPT, 16, iv1, intput,decrypt);
printf("\nInside of decrypt128 function:\n");
for (unsigned index = 0; index < 128; ++index)
printf("%c", (char) decrypt[index]);
strcpy(output, decrypt);
}
int main(int argc, char * argv[]){
int socket_desc, client_sock, c, read_size, rc, option = 1, ret,
encrypt_size, counter_data_receive;
struct sockaddr_in server, client;
int opt = 1;
struct timeval timeout_receive;
unsigned char encrypt_bufferr[MAX_LENGTH_DATA] = { 0 };
unsigned char decrypt_bufferr[MAX_LENGTH_DATA] = { 0 };
// Creating socket file descriptor
printf("Creating socket...!!!!!\n");
if ((socket_desc = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 4434
if (setsockopt(socket_desc, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt,
sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(4434);
// Forcefully attaching socket to the port 4434
if (bind(socket_desc, (struct sockaddr *) &server, sizeof(server)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
c = sizeof(struct sockaddr_in);
printf("Start waiting for incoming connections!\n");
listen(socket_desc, 1);
client_sock = accept(socket_desc, (struct sockaddr*) &client,
(socklen_t*) &c);
if (client_sock < 0) {
printf("Failed: accept connection");
exit(EXIT_FAILURE);
}
printf("Connection accepted\n");
timeout_receive.tv_sec = 5;
timeout_receive.tv_usec = 0;
setsockopt(client_sock, SOL_SOCKET, SO_RCVTIMEO,
(const void*) &timeout_receive, sizeof(struct timeval));
memset(encrypt_bufferr, 0x00, sizeof(encrypt_bufferr));
memset(decrypt_bufferr, 0x00, sizeof(decrypt_bufferr));
ret = recv(client_sock, encrypt_bufferr, sizeof(encrypt_bufferr), 0);
printf("\n+++++++++++++byte receive: %d\n", ret);
printf("\n+++++++++++++received buff: %s\n", encrypt_bufferr);
decrypt128(encrypt_bufferr, decrypt_bufferr);
printf("\nFinal decrypted data = %s", decrypt_bufferr);
}
output
Creating socket...!!!!!
Start waiting for incoming connections!
Connection accepted
+++++++++++++byte receive: 24
+++++++++++++received buff: 8+4c4xcMC1FPhdJabnl/4w==
Inside of decrypt128 function:
R�V͵2�Q���˵��
For the client-side, I wrote it using Java:
public class EncryptDecryptString {
private static final String cipherTransformation = "AES/CBC/PKCS5PADDING";
private static final String aesEncryptionAlgorithem = "AES";
public static String encrypt(String plainText) {
String encryptedText = "";
byte iv1[] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P' };
try {
Cipher cipher = Cipher.getInstance(cipherTransformation);
byte[] key = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P' };
SecretKeySpec secretKey = new SecretKeySpec(key, aesEncryptionAlgorithem);
IvParameterSpec ivparameterspec = new IvParameterSpec(iv1);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivparameterspec);
byte[] cipherText = cipher.doFinal(plainText.getBytes("UTF-8"));
Base64.Encoder encoder = Base64.getEncoder();
encryptedText = encoder.encodeToString(cipherText);
} catch (Exception E) {
System.err.println("Encrypt Exception : "+E.getMessage());
}
return encryptedText;
}
public static String decrypt(String encryptedText) {
String decryptedText = "";
byte iv1[] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P' };
try {
Cipher cipher = Cipher.getInstance(cipherTransformation);
byte[] key = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P' };//encryptionKey.getBytes(characterEncoding);
SecretKeySpec secretKey = new SecretKeySpec(key, aesEncryptionAlgorithem);
IvParameterSpec ivparameterspec = new IvParameterSpec(iv1);
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivparameterspec);
Base64.Decoder decoder = Base64.getDecoder();
byte[] cipherText = decoder.decode(encryptedText.getBytes("UTF8"));
decryptedText = new String(cipher.doFinal(cipherText), "UTF-8");
} catch (Exception E) {
System.err.println("decrypt Exception : "+E.getMessage());
}
return decryptedText;
}
public static void main(String[] args) {
//System.out.println("Enter String : ");
System.out.println("Running.... ");
String plainString = "Hello world!";//sc.nextLine();
String encyptStr = encrypt(plainString);
String decryptStr = decrypt(encyptStr);
Socket socketOfClient;
try {
socketOfClient = new Socket("127.0.0.1", 4434);
BufferedWriter os = new BufferedWriter(new OutputStreamWriter(socketOfClient.getOutputStream()));
BufferedReader is = new BufferedReader(new InputStreamReader(socketOfClient.getInputStream()));
os.write(encyptStr);
os.flush();
System.out.printf("\nSent data to server....\n");
//os.flush();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Plain String : "+plainString);
System.out.println("Encrypt String : "+encyptStr);
System.out.println("Decrypt String : "+decryptStr);
}
}
Output
Running....
Sent data to server....
Plain String : Hello world!
Encrypt String : 8+4c4xcMC1FPhdJabnl/4w==
Decrypt String : Hello world!
The received encrypted data is the same between the two sides, but when I used mbedtl to decrypt this data in the server-side, the result is not the same. Please help me to resolve the problem. Thank you!!!!
I am unable to get the same output from HMAC in C++ like the one i wrote in java, they have different output.
Java:
private static byte[] hmac_sha(String crypto, byte[] keyBytes, byte[] text) {
try {
Mac hmac;
hmac = Mac.getInstance(crypto);
SecretKeySpec macKey = new SecretKeySpec(keyBytes, "RAW");
hmac.init(macKey);
return hmac.doFinal(text);
} catch (GeneralSecurityException gse) {
throw new UndeclaredThrowableException(gse);
}
}
C++:
BYTE *key = (BYTE *)encodedSeed.data();
BYTE digest[20];
const char *message = encodedTime.data();
CHMAC_SHA1 HMAC;
HMAC.HMAC_SHA1((BYTE *)message, strlen(message), key, sizeof(key), digest);
wstring finalDigest;
for (int i = 0; i < 20; i++){
finalDigest.push_back(std::btowc(digest[i]));
}
return finalDigest;
I have an encryption/decryption algorithm and I'm trying to encrypt some special characters to send to the server from android, but it is throwing an exception:
java.lang.Exception: [encrypt] error:0607F08A:digital envelope routines:EVP_EncryptFinal_ex:data not multiple of block length
Normal Latin characters are encrypted/decrypted fine, but special characters aren't.
Here is my code:
public class MCrypt {
private String iv = "fedcba9876543210";//Dummy iv (CHANGE IT!)
private IvParameterSpec ivspec;
private SecretKeySpec keyspec;
private Cipher cipher;
private String SecretKey = "0123456789abcdef";//Dummy secretKey (CHANGE IT!)
public MCrypt()
{
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" + Integer.toHexString(data[i]&0xFF);
else
str = str + 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 = 32;
int x = source.length() % size;
int padLength = size - x;
for (int i = 0; i < padLength; i++)
{
source += paddingChar;
}
return source;
}
}
Does anyone know what the problem here is?
Thanks!
Change this line:
cipher = Cipher.getInstance("AES/CBC/NoPadding");
To
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
From this Blog
Change this line :
cipher = Cipher.getInstance("AES/CBC/NoPadding"); //this may be not decrypt full plaintext.
To:
cipher = Cipher.getInstance("AES/ECB/PKCS7Padding"); // use this for descrypt full plain text without lost.
I have a PHP servor which decrypt data in 3DES with the CFB Mode
I encrypt in PHP :
$montant = "500";
$message_crypte = mcrypt_encrypt(MCRYPT_3DES, "N4y1FRDRJ7wn7eJNnWaahCIS", $montant, ,CRYPT_MODE_CFB, "NCNPJDcR");
$montant = base64_encode($message_crypte);
This script in PHP is OK with other system.
And I want to encrypt in Java :
public class CryptData {
private KeySpec keySpec;
private SecretKey key;
private IvParameterSpec iv;
public CryptData(String keyString, String ivString) {
try {
final MessageDigest md = MessageDigest.getInstance("md5");
final byte[] digestOfPassword = md.digest(Base64
.decodeBase64(keyString.getBytes("ISO-8859-1")));
final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
for (int j = 0, k = 16; j < 8;) {
keyBytes[k++] = keyBytes[j++];
}
//keySpec = new DESedeKeySpec(keyBytes);
keySpec = new DESedeKeySpec(keyString.getBytes());
key = SecretKeyFactory.getInstance("DESede")
.generateSecret(keySpec);
iv = new IvParameterSpec(ivString.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
}
public String encrypt(String value) {
try {
Cipher ecipher = Cipher.getInstance("DESede/CFB/NoPadding");
//"SunJCE");
ecipher.init(Cipher.ENCRYPT_MODE, key, iv);
if (value == null)
return null;
// Encode the string into bytes using utf-8
byte[] valeur = value.getBytes("ISO-8859-1");
//byte[] utf8 = value.getBytes();
// Encrypt
byte[] enc = ecipher.doFinal(valeur);
// Encode bytes to base64 to get a string
return new String(Base64.encodeBase64(enc), "ISO-8859-1");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
I have not the same result in PHP and in Java
How modify Java treatment to obtain the same result as PHP?
The answer is:
Cipher ecipher = Cipher.getInstance("DESede/CFB8/NoPadding");
I need to use "CFB8"
I'm having a lot of trouble converting the following code to Objective-C, can anyone lend a hand:
public String encodeString(String s) {
try {
// Create MD5 Hash
MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
digest.update(s.getBytes());
byte messageDigest[] = digest.digest();
Base64 b = null;
return b.encodeToString(messageDigest,1);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
This should work:
#import <CommonCrypto/CommonDigest.h>
- (NSString *) encodeString:(NSString *) s {
const char *cStr = [s UTF8String];
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(cStr, strlen(cStr), result);
NSMutableString *result = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; ++i) {
[result appendFormat:#"%02x", result[i]];
}
return [NSString stringWithString:result];
}