I'm very new to programming and I've been trying to encrypt a message using Arduino and decrypting with Python.
On the Arduino, I managed to encrypt and decrypt correctly, but when I try to decrypt with Python it doesn't show an error but the result isn't right.
I've used the library AESlib with the latest version (2.2.1) on Arduino with MEGA2560.
On the Arduino part I encrypted and decrypted the message correctly, I used the simple example that the AESlib offer but changed a bit to be able to do what I need it, encrypting with AES and encoding with base64, and then decoding with base64 to be able to decrypt with AES again. When that worked I printed the base64 encoded message and then copied it into a function on the python program and tried to decrypt it without working.
On the Python part, I've used the CBC mode for the decryption. Copied the key, the IV, and the encoded message for then decoded and decrypted.
Here is the message with the key and IV that I've used:
#define INPUT_BUFFER_LIMIT (400 + 1) //Maximum message caracters
unsigned char cleartext[INPUT_BUFFER_LIMIT] = {0}; // THIS IS INPUT BUFFER (FOR TEXT)
unsigned char ciphertext[2*INPUT_BUFFER_LIMIT] = {0}; // THIS IS OUTPUT BUFFER (FOR BASE64-ENCODED ENCRYPTED DATA)
unsigned char decryptedtext[INPUT_BUFFER_LIMIT] = {0}; // THIS IS OUTPUT BUFFER (FOR DECRYPTED TEXT)
unsigned char readBuffer[399] = "0013;0013;0013;15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3;NULL";//THIS IS THE VARIABLE THAT CONTAINS THE MESSAGE TO ENCRYPT
byte aes_key[N_BLOCK] = "06a9214036b8a15b512e03d534120006"; // THIS IS THE VARIABLE THAT CONTAINS THE KEY
byte aes_iv[N_BLOCK] = "6543210987654"; // THIS IS THE VARIABLE THAT CONTAINS THE IV
Arduino code:
#include "AESLib.h"
#define BAUD 9600
AESLib aesLib;
#define INPUT_BUFFER_LIMIT (400 + 1)
unsigned char cleartext[INPUT_BUFFER_LIMIT] = {0}; // THIS IS INPUT BUFFER (FOR TEXT)
unsigned char ciphertext[2*INPUT_BUFFER_LIMIT] = {0}; // THIS IS OUTPUT BUFFER (FOR BASE64-ENCODED ENCRYPTED DATA)
unsigned char decryptedtext[INPUT_BUFFER_LIMIT] = {0}; // THIS IS OUTPUT BUFFER (FOR DECRYPTED TEXT)
unsigned char readBuffer[399] = "0013;0013;0013;15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3;NULL";//THIS IS THE VARIABLE THAT CONTAINS THE MESSAGE TO ENCRYPT
byte aes_key[N_BLOCK] = "06a9214036b8a15b512e03d534120006"; // THIS IS THE VARIABLE THAT CONTAINS THE KEY
byte aes_iv[N_BLOCK] = "6543210987654"; // THIS IS THE VARIABLE THAT CONTAINS THE IV
// Generate IV
void aes_init() {
aesLib.gen_iv(aes_iv);
aesLib.set_paddingmode((paddingMode)0);
}
uint16_t encrypt_to_ciphertext(char * msg, uint16_t msgLen, byte iv[]) {
int i = 0;
Serial.println("Calling encrypt (string)...");
int cipherlength = aesLib.encrypt((byte*)msg, msgLen, (char*)ciphertext, aes_key, sizeof(aes_key), iv);
// uint16_t encrypt(byte input[], uint16_t input_length, char * output, byte key[],int bits, byte my_iv[]);
return cipherlength;
}
uint16_t decrypt_to_cleartext(byte msg[], uint16_t msgLen, byte iv[]) {
int i = 0;
Serial.print("Calling decrypt...; ");
uint16_t dec_bytes = aesLib.decrypt(msg, msgLen, (char*)decryptedtext, aes_key, sizeof(aes_key), iv);
Serial.print("Decrypted bytes: "); Serial.println(dec_bytes);
return dec_bytes;
}
void setup() {
Serial.begin(BAUD);
Serial.setTimeout(60000);
delay(2000);
aes_init(); // generate random IV, should be called only once? causes crash if repeated...
Serial.println(readBuffer[2]);
}
/* non-blocking wait function */
void wait(unsigned long milliseconds) {
unsigned long timeout = millis() + milliseconds;
while (millis() < timeout) {
yield();
}
}
byte enc_iv_to[N_BLOCK] = "6543210987654"; //A COPY OF THE IV TO DECRYPT WITH THE SAME IV
void loop() {
int i = 0;
Serial.print("readBuffer length: "); Serial.println(sizeof(readBuffer));
// must not exceed INPUT_BUFFER_LIMIT bytes; may contain a newline
sprintf((char*)cleartext, "%s", readBuffer);
// Encrypt
// iv_block gets written to, provide own fresh copy... so each iteration of encryption will be the same.
uint16_t msgLen = sizeof(readBuffer);
memcpy(aes_iv, enc_iv_to, sizeof(enc_iv_to));
uint16_t encLen = encrypt_to_ciphertext((char*)cleartext, msgLen, aes_iv); //CALL THE FUNCTION TO ENCRYPT THE MESSAGE
unsigned char base64encoded[2*INPUT_BUFFER_LIMIT] = {0};
base64_encode((char*)base64encoded, (char*)ciphertext, sizeof(ciphertext)); //CALL THE FUNCTION TO ENCODE THE ENCRYPTED MESSAGE
Serial.println("ciphertext_base64_encoded");
Serial.println((char*)base64encoded);
delay(5000);
Serial.print("Encrypted length = "); Serial.println(encLen);
Serial.print("Encrypted base64 length = "); Serial.println(sizeof(base64encoded));
Serial.println("Encrypted. Decrypting..."); Serial.println(sizeof(base64encoded)); Serial.flush();
unsigned char base64decoded[2*INPUT_BUFFER_LIMIT] = {0};
base64_decode((char*)base64decoded, (char*)base64encoded, sizeof(base64encoded));
Serial.println((char*)base64decoded);
delay(3000);
memcpy(aes_iv, enc_iv_to, sizeof(enc_iv_to));
uint16_t decLen = decrypt_to_cleartext((char*)base64decoded, encLen, aes_iv);
Serial.print("Decrypted cleartext of length: "); Serial.println(decLen);
Serial.print("Decrypted cleartext:\n"); Serial.println((char*)decryptedtext);
if (strcmp((char*)readBuffer, (char*)decryptedtext) == 0) {
Serial.println("Decrypted correctly.");
} else {
Serial.println("Decryption test failed.");
}
delay(3000);
Serial.println("---");
exit(0);
}
Python code:
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad, pad
from Crypto.Random import get_random_bytes
from Crypto.Util.strxor import strxor
import random, base64, hashlib, getpass, argparse, re
def decrypt_CBC_base64(key, ciphertext_base64, iv):
ciphertext_base64 += "=" * ((4 - len(ciphertext_base64) % 4) % 4)
ciphertext = base64.b64decode(ciphertext_base64)
ciphertext = pad (ciphertext, 16)
py_bytes = decrypt_CBC(key, ciphertext, iv)
return py_bytes
def decrypt_CBC(key, ciphertext, iv):
cipher = AES.new(key, AES.MODE_CBC, iv)
pt_bytes = cipher.decrypt(ciphertext)
return pt_bytes
try:
key = b'06a9214036b8a15b512e03d534120006'
iv = b'6543210987654321'
plaintext = b'0013;0013;0013;15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3,15.3;NULL'
ciphertext_base64 = 'aS/80Cy1jEqiclhtrYmqkYmLsxlKERuSeTfSGHfmN86N/VJHizQEmLAUJ8T7qlIgNZVr1EZzNCG2/8qzwRwHoLdMmmZKjIOKPSpbqWfiMRbvZNoREnOBv8EtGIDM4GElUvGCdJ1FYYT+S2ThZB71cRjM+oOn53w6tIQwgNuUHuZ9UMzOVBtcNKVJRUs93CXZs76qZdy7amNTyYEFkuqRjBEvA+dM8ucaxrJUUhrKfbXn2bIqHDeRJr7nldnNSqn3yT98uzJzz/YHZm4I0ZKtP3P3G7LfCmm2tGlKFiUBVsIKF+Z7WD9PHqZ55x7cHZrk3Y1T1j0l9LOIj0BHj5pjkH5ilAW0+kMU9+iyPD1AVO600U41EcPD9Iohw0pU13ooFn4Q+HDgXBHzV9Aufx8ORkw/5U/okjNxujhp07Xg/chbBXQBR1tzHgoj//XZoD5l/G+zrJVmOXCffRipV08PjbN9dDYjaFMmTsAcCBCNWd8yUGsEwOuv/cePuYSrALg3hh/tfaMZ0/H7C2gvS4XMHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
print(ciphertext_base64)
decrypted = decrypt_CBC_base64(key, ciphertext_base64, iv)
print(decrypted)
except Exception as err:
print("error: {0}".format(err))
except KeyboardInterrupt:
print("\n\n[*] (Ctrl-C) Detected, shutting down...")
exit()
Any solutions? Hope there's enough information.
The AESLib iterates over data in 16 byte chunks, encrypting one chunk of 16 bytes at a time. To decrypt the data in Python using the pycryptodome library, you would need to decrypt 16 bytes at a time and then concatenate all the decrypted data together.
I create a file:
m_fileHandle = CreateFileA(
m_pszFilename,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
NULL);
Then write to it:
const BOOL bSuccess = WriteFile(
m_fileHandle,
buffer,
dataSize,
&tempBytesWritten,
NULL );
When I start the program, WriteFile fails and GetLastError() returns error 87.
I read that WriteFile on a file created with flag FILE_FLAG_NO_BUFFERING fails when dataSize is not a multiple of hard disk sector size.
If that is the reason for the error, then why does the code work fine when I debug in Visual Studio Express 2012?
Solution was here: File Buffering https://msdn.microsoft.com/en-us/library/windows/desktop/cc644950%28v=vs.85%29.aspx
Working code:
#include "stdafx.h"
#include "assert.h"
#include <iostream>
#include <Windows.h>
#include <comutil.h>
using namespace std;
namespace{
unsigned long tempBytesWritten = 0;
HANDLE m_fileHandle;
char m_pszFilename[_MAX_PATH] = "";
// Create a temporary file for benchmark
int createFile()
{
WCHAR tempPath[MAX_PATH];
GetTempPath(_countof(tempPath), tempPath);
_bstr_t p(tempPath);
const char* c = p;
strcpy(m_pszFilename, c);
strcat(m_pszFilename, "testRawFile.raw");
cout << "Writing to " << m_pszFilename << endl;
m_fileHandle = CreateFileA(
m_pszFilename,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
NULL);
if (m_fileHandle == INVALID_HANDLE_VALUE)
{
assert( false );
}
return 0;
}
}
DWORD DetectSectorSize( WCHAR * devName, PSTORAGE_ACCESS_ALIGNMENT_DESCRIPTOR pAlignmentDescriptor)
{
DWORD Bytes = 0;
BOOL bReturn = FALSE;
DWORD Error = NO_ERROR;
STORAGE_PROPERTY_QUERY Query;
ZeroMemory(&Query, sizeof(Query));
HANDLE hFile = CreateFileW( devName,
STANDARD_RIGHTS_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile==INVALID_HANDLE_VALUE) {
wprintf(L" hFile==INVALID_HANDLE_VALUE. GetLastError() returns %lu.\n", Error=GetLastError());
return Error;
}
Query.QueryType = PropertyStandardQuery;
Query.PropertyId = StorageAccessAlignmentProperty;
bReturn = DeviceIoControl( hFile,
IOCTL_STORAGE_QUERY_PROPERTY,
&Query,
sizeof(STORAGE_PROPERTY_QUERY),
pAlignmentDescriptor,
sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR),
&Bytes,
NULL);
if (bReturn == FALSE) {
wprintf(L" bReturn==FALSE. GetLastError() returns %lu.\n", Error=GetLastError());
}
CloseHandle(hFile);
return Error;
}
int main()
{
unsigned int dataSize = 2000;
DWORD Error = NO_ERROR;
STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR Alignment = {0};
// WCHAR szDisk[] = L"\\\\.\\PhysicalDrive0";
WCHAR szDisk[] = L"\\\\.\\C:";
Error = DetectSectorSize(szDisk, &Alignment);
if (Error) {
wprintf(L"Error %lu encountered while querying alignment.\n", Error);
return Error;
}
wprintf(L"Disk %s Properties\n", (WCHAR*) szDisk);
if (Alignment.BytesPerLogicalSector < Alignment.BytesPerPhysicalSector) {
wprintf(L" Emulated sector size is %lu bytes.\n", Alignment.BytesPerLogicalSector);
}
wprintf(L" Physical sector size is %lu bytes.\n", Alignment.BytesPerPhysicalSector);
dataSize = ((unsigned int)(dataSize + Alignment.BytesPerPhysicalSector - 1)/Alignment.BytesPerPhysicalSector) * Alignment.BytesPerPhysicalSector;
// Allocate buffer for file
unsigned char *buffer = new unsigned char[dataSize];
// Create file to write to
if ( createFile() != 0 )
{
printf("There was error creating the files... press Enter to exit.");
getchar();
return -1;
}
const BOOL bSuccess = WriteFile(m_fileHandle, buffer, dataSize, &tempBytesWritten, NULL );
if (!bSuccess)
{
cout << "Write failed with error " << GetLastError() << endl;
}
// clean up and remove file
CloseHandle(m_fileHandle);
wchar_t wtext[_MAX_PATH];
mbstowcs(wtext, m_pszFilename, strlen(m_pszFilename)+1);
DeleteFile(wtext);
return 0;
}
I have here the following data for which I have to find the sha1 digest using openssl.
data:
AwAIAOwIAAABABwAgAIAABYAAAAAAAAAAAAAAHQAAAAAAAAAAAAAAAgAAAAkAAAAQgAAAFQAAABsAAAAhgAAAJgAAACuAAAAwgAAAM4AAADsAAAAAgEAAAwBAAAoAQAARgEAAFgBAACwAQAAtAEAANABAADkAQAA+gEAAAIAaQBkAAAADABsAGEAeQBvAHUAdABfAHcAaQBkAHQAaAAAAA0AbABhAHkAbwB1AHQAXwBoAGUAaQBnAGgAdAAAAAcAZwByAGEAdgBpAHQAeQAAAAoAYgBhAGMAawBnAHIAbwB1AG4AZAAAAAsAbwByAGkAZQBuAHQAYQB0AGkAbwBuAAAABwBwAGEAZABkAGkAbgBnAAAACQB0AGUAeAB0AEMAbwBsAG8AcgAAAAgAdABlAHgAdABTAGkAegBlAAAABAB0AGUAeAB0AAAADQBwAGEAZABkAGkAbgBnAEIAbwB0AHQAbwBtAAAACQBzAGMAYQBsAGUAVAB5AHAAZQAAAAMAcwByAGMAAAAMAHAAYQBkAGQAaQBuAGcAUgBpAGcAaAB0AAAADQBsAGEAeQBvAHUAdABfAHcAZQBpAGcAaAB0AAAABwBhAG4AZAByAG8AaQBkAAAAKgBoAHQAdABwADoALwAvAHMAYwBoAGUAbQBhAHMALgBhAG4AZAByAG8AaQBkAC4AYwBvAG0ALwBhAHAAawAvAHIAZQBzAC8AYQBuAGQAcgBvAGkAZAAAAAAAAAAMAEwAaQBuAGUAYQByAEwAYQB5AG8AdQB0AAAACABUAGUAeAB0AFYAaQBlAHcAAAAJAEkAbQBhAGcAZQBWAGkAZQB3AAAABgBCAHUAdAB0AG8AbgAAAAAAgAEIAEQAAADQAAEB9AABAfUAAQGvAAEB1AABAcQAAQHVAAEBmAABAZUAAQFPAQEB2QABAR0BAQEZAQEB2AABAYEBAQEAARAAGAAAABEAAAD/////DwAAABAAAAACARAAsAAAABEAAAD//////////xIAAAAUABQABwAAAAAAAAAQAAAAAwAAAP////8IAAAREQAAABAAAAAFAAAA/////wgAABABAAAAEAAAAAAAAAD/////CAAAAR0AB38QAAAABAAAAP////8IAAABEQAGfxAAAAAGAAAA/////wgAAAUBEAAAEAAAAAEAAAD/////CAAAEP////8QAAAAAgAAAP////8IAAAQ/////wIBEACcAAAAGgAAAP//////////EwAAABQAFAAGAAAAAAAAABAAAAAIAAAA/////wgAAAUCEgAAEAAAAAcAAAD/////CAAAARAABn8QAAAACgAAAP////8IAAAFARgAABAAAAABAAAA/////wgAABD/////EAAAAAIAAAD/////CAAAEP7///8QAAAACQAAAP////8IAAABRwAIfwMBEAAYAAAAIAAAAP//////////EwAAAAIBEAB0AAAAIgAAAP//////////EgAAABQAFAAEAAAAAAAAABAAAAAFAAAA/////wgAABAAAAAAEAAAAAQAAAD/////CAAAAREABn8QAAAAAQAAAP////8IAAAQ/////xAAAAACAAAA/////wgAABD+////AgEQAIgAAAAoAAAA//////////8UAAAAFAAUAAUAAAAAAAAAEAAAAA0AAAD/////CAAABQEYAAAQAAAAAQAAAP////8IAAAQ/v///xAAAAACAAAA/////wgAABD+////EAAAAAwAAAD/////CAAAAQEAAn8QAAAACwAAAP////8IAAAQBQAAAAMBEAAYAAAALQAAAP//////////FAAAAAIBEAB0AAAALwAAAP//////////EgAAABQAFAAEAAAAAAAAABAAAAAFAAAA/////wgAABABAAAAEAAAAAEAAAD/////CAAABQEAAAAQAAAAAgAAAP////8IAAAQ/v///xAAAAAOAAAA/////wgAAAQAAIA/AgEQAHQAAAA1AAAA//////////8VAAAAFAAUAAQAAAAAAAAAEAAAAAAAAAD/////CAAAASgAB38QAAAAAQAAAP////8IAAAQ/////xAAAAACAAAA/////wgAABD+////EAAAAAkAAAD/////CAAAARUACH8DARAAGAAAADgAAAD//////////xUAAAACARAAdAAAADoAAAD//////////xUAAAAUABQABAAAAAAAAAAQAAAAAAAAAP////8IAAABKgAHfxAAAAABAAAA/////wgAABD/////EAAAAAIAAAD/////CAAAEP7///8QAAAACQAAAP////8IAAABGgAIfwMBEAAYAAAAPQAAAP//////////FQAAAAMBEAAYAAAAPwAAAP//////////EgAAAAIBEAB0AAAAQQAAAP//////////EgAAABQAFAAEAAAAAAAAABAAAAAFAAAA/////wgAABABAAAAEAAAAAEAAAD/////CAAABQEAAAAQAAAAAgAAAP////8IAAAQ/v///xAAAAAOAAAA/////wgAAAQAAIA/AgEQAHQAAABHAAAA//////////8VAAAAFAAUAAQAAAAAAAAAEAAAAAAAAAD/////CAAAASkAB38QAAAAAQAAAP////8IAAAQ/////xAAAAACAAAA/////wgAABD+////EAAAAAkAAAD/////CAAAARYACH8DARAAGAAAAEoAAAD//////////xUAAAACARAAdAAAAEwAAAD//////////xUAAAAUABQABAAAAAAAAAAQAAAAAAAAAP////8IAAABKwAHfxAAAAABAAAA/////wgAABD/////EAAAAAIAAAD/////CAAAEP7///8QAAAACQAAAP////8IAAABGQAIfwMBEAAYAAAATwAAAP//////////FQAAAAMBEAAYAAAAUQAAAP//////////EgAAAAMBEAAYAAAAUwAAAP//////////EgAAAAMBEAAYAAAAVQAAAP//////////EgAAAAEBEAAYAAAAVQAAAP////8PAAAAEAAAABgAAAA9AAAA//////////8fAAAAAgEQAGAAAAA/AAAA//////////8eAAAAFAAUAAMAAAAAAAAAGQAAAAUAAAD/////CAAAEAAAAAAZAAAAAAAAAP////8IAAAQ/v///xkAAAABAAAA/////wgAABD+////AgEQAMQAAABEAAAA//////////8gAAAAFAAUAAgAAAAAAAAAGQAAABIAAAD/////CAAABQIOAAAZAAAAEQAAAP////8IAAARAQAAABkAAAAQAAAA/////wgAAAEGAAZ/GQAAAAIAAAD/////CAAAARIAB38ZAAAAEwAAAP////8IAAAFAQQAABkAAAAAAAAA/////wgAABD+////GQAAAAEAAAD/////CAAAEP7///8ZAAAADwAAAP////8IAAABMwAIfwMBEAAYAAAASwAAAP//////////IAAAAAIBEACIAAAATQAAAP//////////IAAAABQAFAAFAAAAAAAAABkAAAASAAAA/////wgAAAUCDgAAGQAAABAAAAD/////CAAAAQYABn8ZAAAAAgAAAP////8IAAABEwAHfxkAAAAAAAAA/////wgAABD+////GQAAAAEAAAD/////CAAAEP7///8DARAAGAAAAFEAAAD//////////yAAAAADARAAGAAAAFMAAAD//////////x4AAAACARAAYAAAAFUAAAD//////////x4AAAAUABQAAwAAAAAAAAAZAAAABQAAAP////8IAAAQAAAAABkAAAAAAAAA/////wgAABD+////GQAAAAEAAAD/////CAAAEP7///8CARAAxAAAAFoAAAD//////////yAAAAAUABQACAAAAAAAAAAZAAAAEgAAAP////8IAAAFAg4AABkAAAARAAAA/////wgAABEBAAAAGQAAABAAAAD/////CAAAAQYABn8ZAAAAAgAAAP////8IAAABFAAHfxkAAAATAAAA/////wgAAA
The digest as given to me is:
Wk2pJnOErEHsElMw4TMX+rjHsQQ=
But when I use(f1= file where I copied the above data):
base64 -d f1.txt | openssl dgst -sha1 -binary | base64
I get a "base64: invalid input" error and the following digest which seems completely different :(
BaRlDid73RYBFMgqveC8G+gFBBU=
Can somebody confirm and explain if there is some mistake??
UPDATED:
Scenario: Client's binary file is base64 encoded and sent to server. Server decodes this and computes the sha1 digest. Since I have client's base64 encoded sha1 digest, the server also encodes the digest to base64. Now these two should match. And it doesn't! I receive all data. I have rechecked it. I shall present part of the code here:
//RCVBUFSIZE = 1024 (defined)
void HandleClient(int clntSocket)
{
char echoBuffer[RCVBUFSIZE] ; /* Buffer for echo string */
memset(echoBuffer, 0, RCVBUFSIZE);
char inBuffer; /* Buffer for first string */
char recv_data;
int recvMsgSize = 0; /* Size of received message */
char replyBuffer[32];
int bytes_received = 0;
int rv = 0;
int connected = clntSocket;
int len= 0;
int i = 0;
EVP_MD_CTX md_ctx;
const EVP_MD *md;
unsigned char md_value[EVP_MAX_MD_SIZE];
unsigned int md_len;
OpenSSL_add_all_digests();
md = EVP_get_digestbyname("sha1");
EVP_MD_CTX_init(&md_ctx);
EVP_DigestInit_ex(&md_ctx, md, NULL);
/* Receive message from client */
while (((bytes_received = recv(connected,&inBuffer,1,0)) > 0) && (inBuffer != '\n')){
/* Send received string and receive again until end of transmission */
if (bytes_received > 0) /* zero indicates end of transmission */
{
printf("Message received from Client is : %c\n", inBuffer);
char n = inBuffer;
int indicator = 0;
int current = 0;
unsigned long fileLen;
if(n =='6'){
if ((recvMsgSize = recv(connected, echoBuffer, RCVBUFSIZE, 0)) < 0)
DieWithError("recv() failed");
printf("no. of bytes got : %d\n", recvMsgSize);
if (recvMsgSize > 0)
echoBuffer[recvMsgSize] = '\0';
len= atoi(echoBuffer);
char *data =NULL;
printf("length of following message : %d\n", len);
if(len>0){
for( i = RCVBUFSIZE; i < (len+RCVBUFSIZE); i=i+RCVBUFSIZE){
if(i>len)
recvMsgSize = recv(connected, echoBuffer, (len - (i-RCVBUFSIZE)), 0);
else
recvMsgSize = recv(connected, echoBuffer, RCVBUFSIZE, 0);
echoBuffer[recvMsgSize] = '\0';
decode(echoBuffer, recvMsgSize, "file_out");
data = readFileBuffer("file_out");
EVP_DigestUpdate(&md_ctx, data, strlen(data));
}
}
len = 0;
memset(echoBuffer, 0, RCVBUFSIZE);
recvMsgSize = 0;
}
if (n =='5'){
printf("Update Digest Over- Calculate Final Dgst!!!!! \n");
n= 0;
EVP_DigestFinal_ex(&md_ctx, md_value, &md_len); //retrieve digest from ctx unto md_value and #bytes written is copied into md_len
EVP_MD_CTX_cleanup(&md_ctx);
FILE *f;
f = fopen("file_sha1", "w");
printf("\n");
printf("******************************************************\n ");
printf("Digest is: ");
for(i = 0; i < md_len; i++){
if ( f !=NULL){
fputc(md_value[i], f);
}
printf("%02x", md_value[i]);
}
printf("\n");
printf("******************************************************\n ");
fclose(f);
}
printf("socket closing\n");
close(connected); /* Close client socket */
}
}
char *readFileBuffer(char *name)
{
FILE *file;
char *buffer = NULL;
unsigned long fileLen;
//Open file
file = fopen(name, "rb");
if (!file)
{
fprintf(stderr, "Unable to open file %s", name);
return;
}
//Get file length
fseek(file, 0, SEEK_END);
fileLen=ftell(file);
printf("file length = %ld\n", fileLen);
fseek(file, 0, SEEK_SET);
//printf("Allocate memory\n");
buffer=(char *)malloc(fileLen+1);
printf("length of write buffer = %d\n", strlen(buffer));
if (!buffer)
{
fprintf(stderr, "Memory error!");
}
long int n = fread(buffer,1, fileLen,file);
buffer[n] = '\0';
printf("Read no. of bytes = %ld into buffer \n", n);
printf("len of buffer %d \n", strlen(buffer));
if (!buffer)
{
fprintf(stderr, "Memory error!");
fclose(file);
}
fclose(file);
//free(name);
return buffer;
}
// reads b64 encoded msg (ReadBuffer) and writes to WriiteFile.
void decode(char *ReadBuffer, int Length, char *WriteFile)
{
char *msg = (char *)malloc(Length);
memset(msg, 0x00, Length);
int readbytes = -1;
printf("buffer write file %s\n", WriteFile);
// the decode msg is written to this bio
BIO *fileWrBIO = BIO_new_file(WriteFile, "w");
BIO *b64 = BIO_new(BIO_f_base64());
BIO *bio = BIO_new_mem_buf(ReadBuffer, Length);
bio = BIO_push(b64, bio);
BIO_set_flags(bio,BIO_FLAGS_BASE64_NO_NL);
while ((readbytes = BIO_read(bio, msg, Length)) > 0)
{
printf("readbytes: %d\n", readbytes);
BIO_write(fileWrBIO, msg, readbytes);
BIO_flush(fileWrBIO);
memset(msg, 0x00, sizeof(msg));
}
free(msg);
BIO_free_all(bio);
BIO_free_all(fileWrBIO);
}
FWIW...
There are implementations where base64 cannot read its own output.
# base64 ssh_host_rsa_key | base64 -d
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA7qHASF1Jgbase64: invalid input
This is on a CentOS 5 machine.
Reason is that base64 produces output with line breaks, which are garbage chars for the decoder.
Solution is to either produce the base64 without linebreaks (-w 0) or make the decoder ignore garbage chars (-i).
Your data is invalid, probably partial. A valid base64 encoded string should have a length multiple of 4. So the different digest output is expected.
You can encrypt using this command
base64 -w 0 < id_rsa
Well, the data doesn't seem to be a valid base64 string. You might be missing some characters.
Just hit this, also on CentOS 5. Both -w 0 and -i were required, -i didn't work alone. e.g.:
tar -cf - /home/backup | gzip | base64 -w 0
base64 -d -i | gunzip | tar -xvf - -C /
worked fine to move a small home directory via copy&paste.