1

I'm trying to create a *.so file for further use in Python using SWIG. In particular I'm using some libraries from openssl (such opensll/bn.h). But somehow it return error ImportError: [...]/auxchash.so: undefined symbol: BN_bn2hex.

I have the file.cpp, auxchash.cpp:

#include auxchash.h

int keygen(int bits, char *p, char *q, char *g, char *hk, char *tk){
  BN_CTX *ctx = BN_CTX_new();
  BIGNUM *bn_p = BN_new();
  BIGNUM *bn_q = BN_new();
  BIGNUM *bn_g = BN_new();
  BIGNUM *bn_hk = BN_new();
  BIGNUM *bn_tk = BN_new();
  BIGNUM *bn_two = BN_new();

  BN_CTX_init(ctx);

  BN_dec2bn(&bn_two, "2"); //initialize a BIGNUM with value 2

  //on non-unix platform needs to initialize the PRNG with randomness
  //or BN_generate_prime_ex may fail

  //computing the safe prime p and q = (p-1)/2
  BN_generate_prime_ex(bn_p, bits, 1, NULL, NULL, NULL);
  BN_sub(bn_q, bn_p, BN_value_one());
  BN_div(bn_q, NULL, bn_q, bn_two, ctx);

  //finding the generator g (for the group QR_p)
  BN_rand_range(bn_g, bn_p);
  BN_mod_exp(bn_g, bn_g, bn_two, bn_p, ctx);

  //choosing the keys hk and tk
  BN_rand_range(bn_tk, bn_q);
  BN_mod_exp(bn_hk, bn_g, bn_tk, bn_p, ctx);

  //converting from BIGNUM to hex
  p = BN_bn2hex(bn_p);
  q = BN_bn2hex(bn_q);
  g = BN_bn2hex(bn_g);
  hk = BN_bn2hex(bn_hk);
  tk = BN_bn2hex(bn_tk);

  //freeing the resources
  BN_CTX_free(ctx);
  BN_free(bn_two);
  BN_free(bn_p);
  BN_free(bn_q);
  BN_free(bn_g);
  BN_free(bn_hk);
  BN_clear_free(bn_tk);

  return 0;
}

The file.h, auxchash.h:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<openssl/bn.h>
#include<openssl/sha.h>
#include<openssl/rand.h>

int keygen(int bits, char *p, char *q, char *g, char *hk, char *tk);

The file.i for the swig module, auxchash.i:

%module auxchash
%{
#define SWIG_FILE_WITH_INIT
#include "auxchash.h"
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<openssl/bn.h>
#include<openssl/sha.h>
#include<openssl/rand.h>
%}

%include "typemaps.i"
%include "cstring.i"

%cstring_bounded_output(char *p, 1024);
%cstring_bounded_output(char *q, 1024);
%cstring_bounded_output(char *g, 1024);
%cstring_bounded_output(char *hk, 1024);
%cstring_bounded_output(char *tk, 1024);
extern int keygen(int bits, char *p, char *q, char *g, char *hk, char *tk);

Finally a file setup.py to create all the needed swig files, setup.py:

from distutils.core import setup, Extension


auxchash_module = Extension('_auxchash',
                       sources=['auxchash_wrap.cxx', 'auxchash.cpp'],
                       )

setup (name = 'auxchash',
   version = '0.1',
   author      = "SWIG Docs",
   description = """Simple swig example from docs""",
   ext_modules = [auxchash_module],
   py_modules = ["auxchash"],
   )

And all of them are compiled with terminal commands:

swig -c++ -python auxchash.i
python setup.py build_ext --inplace

So far so good, it compile without errors. But then when I run a python main:

import auxchash
res,p,q,g,hk,tk = auxchash.keygen(10)

It gives my the following error:

File: "[...]/auxchash.py" import auxchash
File: "[...]/auxchash.py" auxchash=swig_import_helper()
File: "[...]/auxchash.py" return=importlib.import_module('_auxchash')
File: "[...]/__init.py__" __import__(name)`
ImportError: [...]/auxchash.so: undefined symbol: BN_bn2hex

I don't know how to figure it out.

lorsp000
  • 23
  • 5
  • On a quick reading, I think you need `int keygen(int bits, char **p, char **q, char **g, char **hk, char **tk)` so the function can change the pointer in the caller. Something like `*p = BN_bn2hex(bn_p)`. – jww Oct 19 '17 at 02:04
  • Regarding `auxchash.so: undefined symbol: BN_bn2hex`, what does `ldd auxchash.so` show? Is there a dependency on `libcrypto.so`? – jww Oct 19 '17 at 02:06
  • Yes @jww you're right, what you wrote is absolutely correct. But I've experienced trouble even with swig and char **. I decided to adopt this approach since I cannot able to handle double pointer to a char * in swig. See this [link](https://stackoverflow.com/questions/46776757/swig-char-as-a-pointer-to-a-char?noredirect=1#comment80538743_46776757). – lorsp000 Oct 19 '17 at 09:17
  • If you showed real working code for your other question I would have answered it already. Without real code it's just wasting time. You can wrap `char**` entirely sensibly though, if you can actually show such a function that works. – Flexo Oct 19 '17 at 15:45
  • @Flexo u're right. Sorry it was my first question and I'm new in StackOverflow. I deleted the previous question and wrote it better here [link](https://stackoverflow.com/questions/46846754/swig-char-as-a-pointer-to-a-char). – lorsp000 Oct 20 '17 at 10:04
  • Sorry @Flexo but I didn't resolve [that](https://stackoverflow.com/questions/46846754/swig-char-as-a-pointer-to-a-char) question yet. Since u wrote u'd have answered it already if the question would written properly, can u help me now? I'm really stuck on that yet. – lorsp000 Oct 23 '17 at 10:30

1 Answers1

0

You need to link your module against OpenSSL, e.g.something like:

auxchash_module = Extension('_auxchash',
                       sources=['auxchash_wrap.cxx', 'auxchash.cpp'],
                       libraries=['crypto', 'ssl'],
                       )

(You might only need crypto in that list, I can't quite remember/tell right now)

Flexo
  • 87,323
  • 22
  • 191
  • 272
  • Thank you very much! Yep, adding the libraries parameter, it seems to work. (: – lorsp000 Oct 19 '17 at 09:26
  • It works, but now I get another problem. Printing the return variables on my python main it prints some indecipherable characters. On other hand, inside the C++ function, printing the same values I got the correct value. So it's like there is something wrong in the output of the swing module. But `%cstring_bounded_output` should return correctly a char *. Is this linked to the libraries? – lorsp000 Oct 19 '17 at 10:32
  • I tried, to better understand, to write into the return variables the simple string "hello". The python main is unable to get them properly (i.e. it still prints indecipherable characters. – lorsp000 Oct 19 '17 at 11:20
  • I have literally no idea what your keygen function actually does since you've not shown it, or what you wrote in the test case. but likely you're not getting the semantics of output arguments right. – Flexo Oct 19 '17 at 15:43
  • Problem solved! it was just assigning stuff. Instead of using `p = BN_bn2hex(bn_p)`, just use the library function `strcpy(p ,BN_bn2hex(bn_p)`. Thks @Flexo. – lorsp000 Oct 20 '17 at 08:48