Reputation: 1365
I am trying to port this function from Python to C:
import binascii
from Crypto.Util.number import bytes_to_long
# converts from a string to a long
def _strtoLong(s):
s = bytes("".join(s.split()), "UTF-8")
s = binascii.a2b_hex(s)
return bytes_to_long(s)
The string is very long. The resulting number is 2048 bits I believe. I am trying to port this to C using openssl bn structure, but I can't seem to get the correct ouput. Here is the output of each step from the python function, printed as a string representation:
bytes: b'B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371'
a2b_hex: b'\xb1\x0b\x8f\x96\xa0\x80\xe0\x1d\xde\x92\xde^\xae]T\xecR\xc9\x9f\xbc\xfb\x06\xa3\xc6\x9aj\x9d\xcaR\xd2;a`s\xe2\x86u\xa2=\x18\x988\xef\x1e.\xe6R\xc0\x13\xec\xb4\xae\xa9\x06\x11#$\x97\\<\xd4\x9b\x83\xbf\xac\xcb\xdd}\x90\xc4\xbdp\x98H\x8e\x9c!\x9asrN\xff\xd6\xfa\xe5dG8\xfa\xa3\x1aO\xf5[\xcc\xc0\xa1Q\xaf_\r\xc8\xb4\xbdE\xbf7\xdf6\\\x1ae\xe6\x8c\xfd\xa7mM\xa7\x08\xdf\x1f\xb2\xbc.JCq'
bytes_to_long: 124325339146889384540494091085456630009856882741872806181731279018491820800119460022367403769795008250021191767583423221479185609066059226301250167164084041279837566626881119772675984258163062926954046545485368458404445166682380071370274810671501916789361956272226105723317679562001235501455748016154805420913
In C I am doing:
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <stdint.h>
#include <assert.h>
#include <openssl/bn.h>
int char2int(unsigned char input)
{
if(input >= '0' && input <= '9')
return input - '0';
if(input >= 'A' && input <= 'F')
return input - 'A' + 10;
if(input >= 'a' && input <= 'f')
return input - 'a' + 10;
return -1;
}
// This function assumes src to be a zero terminated sanitized string with
// an even number of [0-9a-f] characters, and target to be sufficiently large
void hex2bin(const unsigned char* src, unsigned char* target)
{
while(*src && src[1])
{
*(target++) = char2int(*src)*16 + char2int(src[1]);
src += 2;
}
}
int main()
{
unsigned char buf[512] = "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C6"
"9A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C0"
"13ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD70"
"98488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0"
"A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708"
"DF1FB2BC2E4A4371";
unsigned char P[2049], val[256];
int i;
int len = 256;
for(i=0; i<len; i++){
P[i] = buf[i];
}
fprintf(stderr, "\nbytes=%s\n", P);
hex2bin(P, val);
fprintf(stderr, "\nhex2bin= ");
for(i=0; i<len/2; i++)
fprintf(stderr, "%02x", val[i]);
fprintf(stderr, "\n");
BIGNUM *bn = BN_new();
BN_bin2bn(val, (int)len/2, bn);
fprintf(stderr, "\nbn=");
BN_print_fp(stdout, bn);
char *str = BN_bn2hex(bn);
printf("\n\nbn2hex: %s\n", str);
free(str);
BN_free(bn);
return 0;
}
This is what it prints out:
matthew@matthew-HP-15-Notebook-PC:~/Desktop/crypto/prog$ make
clang -Wall -I../tomsfastmath/src/headers/ -I../openssl/include main.c ../tomsfastmath/libtfm.a ../openssl/libcrypto.a -o bignum
matthew@matthew-HP-15-Notebook-PC:~/Desktop/crypto/prog$ ./bignum
bytes=B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371
hex2bin= b10b8f96a080e01dde92de5eae5d54ec52c99fbcfb06a3c69a6a9dca52d23b616073e28675a23d189838ef1e2ee652c013ecb4aea906112324975c3cd49b83bfaccbdd7d90c4bd7098488e9c219a73724effd6fae5644738faa31a4ff55bccc0a151af5f0dc8b4bd45bf37df365c1a65e68cfda76d4da708df1fb2bc2e4a4371
bn=B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371
bn2hex: B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371
Any ideas how to convert the bn to a long the same as the python?
Upvotes: 2
Views: 3023
Reputation: 11
You can use OpenSSL Bignum functions :
int BN_bn2bin(const BIGNUM *a, unsigned char *to);
BN_bn2bin converts the absolute value of a into big-endian form and stores it at to. to must point to BN_num_bytes(a) bytes of memory.
char *BN_bn2hex(const BIGNUM *a);
char *BN_bn2dec(const BIGNUM *a);
BN_bn2hex() and BN_bn2dec() return printable strings containing the hexadecimal and decimal encoding of a respectively. For negative numbers, the string is prefaced with a leading '-'. The string must be freed later using OPENSSL_free().
The vice-versa functions for these are (which covert char * to BIGNUM data stucture):
BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret);
int BN_hex2bn(BIGNUM **a, const char *str);
int BN_dec2bn(BIGNUM **a, const char *str);
Upvotes: 1
Reputation: 207
According to OpenSSL manual:
int BN_print_fp(FILE *fp, const BIGNUM *a);
BN_print() and BN_print_fp() write the hexadecimal encoding of a, with a leading '-' for negative numbers, to the BIO or FILE fp.
What you need is this:
char *BN_bn2dec(const BIGNUM *a);
BN_bn2hex() and BN_bn2dec() return printable strings containing the hexadecimal and decimal encoding of a respectively. For negative numbers, the string is prefaced with a leading '-'. The string must be freed later using OPENSSL_free().
Upvotes: 0
Reputation: 984
Create an integer value 0. Look at the leftmost character of the string and add a value to your running-total integer equal to the decimal value represented by that character (0 - 15). Then multiply your running total by 16 and move to the next letter / number. Keep doing this until the last place in your hex string, after which you do not multiply by 16.
I cannot quite make out if this is what your code is trying to do or not.
Upvotes: 0