Необходимо зашифровать\расшифровать некие данные с помощью RSA, используя openssl
Для создания ключей есть функция:
RSA *RSA_generate_key(int num, unsigned long e, void (*callback)(int, int, void *), void *cb_arg);
int RSA_public_encrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding);
'''
#define RSA_3 0x3L
#define RSA_F4 0x10001L
'''
RSA_3 = 3
RSA_F4 = 65537
'''
#define RSA_PKCS1_PADDING 1
#define RSA_SSLV23_PADDING 2
#define RSA_NO_PADDING 3
#define RSA_PKCS1_OAEP_PADDING 4
'''
RSA_PKCS1_PADDING = 1
RSA_SSLV23_PADDING = 2
RSA_NO_PADDING = 3
RSA_PKCS1_OAEP_PADDING = 4
class ENGINE(Structure): pass
class BIGNUM(Structure): pass
class BN_MONT_CTX(Structure): pass
class BN_BLINDING(Structure): pass
class RSA_METHOD(Structure): pass
class RSA(Structure): pass
'''
define BN_ULONG unsigned long
'''
BN_ULONG = c_ulong
'''
typedef struct crypto_ex_data_st CRYPTO_EX_DATA;
'''
class CRYPTO_EX_DATA(Structure): pass
'''
typedef struct bignum_ctx BN_CTX;
'''
class BN_CTX(Structure): pass
'''
struct bignum_st
{
BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks. */
int top; /* Index of last used d +1. */
/* The next are internal book keeping for bn_expand. */
int dmax; /* Size of the d array. */
int neg; /* one if the number is negative */
int flags;
};
typedef struct bignum_st BIGNUM;
'''
BIGNUM._fields_ = [
('d', BN_ULONG),
('top', c_int),
('dmax', c_int),
('neg', c_int),
('flags', c_int)
]
'''
/* Used for montgomery multiplication */
struct bn_mont_ctx_st
{
int ri; /* number of bits in R */
BIGNUM RR; /* used to convert to montgomery form */
BIGNUM N; /* The modulus */
BIGNUM Ni; /* R*(1/R mod N) - N*Ni = 1
* (Ni is only stored for bignum algorithm) */
BN_ULONG n0[2];/* least significant word(s) of Ni;
(type changed with 0.9.9, was "BN_ULONG n0;" before) */
int flags;
};
'''
BN_MONT_CTX._fields_ = [
('ri', c_int),
('RR', POINTER(BIGNUM)),
('N', POINTER(BIGNUM)),
('Ni', POINTER(BIGNUM)),
('n0', BN_ULONG * 2),
('flags', c_int),
]
'''
typedef struct bn_blinding_st
{
int init;
BIGNUM *A;
BIGNUM *Ai;
BIGNUM *mod; /* just a reference */
} BN_BLINDING;
'''
BN_BLINDING._fields_ = [
('init', c_int),
('A', POINTER(BIGNUM)),
('Ai', POINTER(BIGNUM)),
('mod', POINTER(BIGNUM)),
]
'''
typedef struct rsa_meth_st
{
/* name of the implementation */
const char *name;
/* encrypt */
int (*rsa_pub_enc)(int flen, unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
/* verify arbitrary data */
int (*rsa_pub_dec)(int flen, unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
/* sign arbitrary data */
int (*rsa_priv_enc)(int flen, unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
/* decrypt */
int (*rsa_priv_dec)(int flen, unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
/* compute r0 = r0 ^ I mod rsa->n (May be NULL for some
implementations) */
int (*rsa_mod_exp)(BIGNUM *r0, BIGNUM *I, RSA *rsa);
/* compute r = a ^ p mod m (May be NULL for some implementations) */
int (*bn_mod_exp)(BIGNUM *r, BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
/* called at RSA_new */
int (*init)(RSA *rsa);
/* called at RSA_free */
int (*finish)(RSA *rsa);
/* RSA_FLAG_EXT_PKEY - rsa_mod_exp is called for private key
* operations, even if p,q,dmp1,dmq1,iqmp
* are NULL
* RSA_FLAG_SIGN_VER - enable rsa_sign and rsa_verify
* RSA_METHOD_FLAG_NO_CHECK - don't check pub/private match
*/
int flags;
char *app_data; /* ?? */
/* sign. For backward compatibility, this is used only
* if (flags & RSA_FLAG_SIGN_VER)
*/
int (*rsa_sign)(int type, unsigned char *m, unsigned int m_len,
unsigned char *sigret, unsigned int *siglen, RSA *rsa);
/* verify. For backward compatibility, this is used only
* if (flags & RSA_FLAG_SIGN_VER)
*/
int (*rsa_verify)(int type, unsigned char *m, unsigned int m_len,
unsigned char *sigbuf, unsigned int siglen, RSA *rsa);
} RSA_METHOD;
'''
RSA_METHOD._fields_ = [
('name', c_ubyte),
('rsa_pub_enc', CFUNCTYPE(c_int, POINTER(c_ubyte), POINTER(c_ubyte), POINTER(RSA), c_int)),
('rsa_pub_dec', CFUNCTYPE(c_int, POINTER(c_ubyte), POINTER(c_ubyte), POINTER(RSA), c_int)),
('rsa_priv_enc', CFUNCTYPE(c_int, POINTER(c_ubyte), POINTER(c_ubyte), POINTER(RSA), c_int)),
('rsa_priv_dec', CFUNCTYPE(c_int, POINTER(c_ubyte), POINTER(c_ubyte), POINTER(RSA), c_int)),
('rsa_mod_exp', CFUNCTYPE(POINTER(BIGNUM), POINTER(BIGNUM), POINTER(RSA))),
('bn_mod_exp', CFUNCTYPE(POINTER(BIGNUM), POINTER(BIGNUM), POINTER(BIGNUM), POINTER(BIGNUM), POINTER(BN_CTX), POINTER(BN_MONT_CTX))),
('init', CFUNCTYPE(POINTER(RSA))),
('finish', CFUNCTYPE(POINTER(RSA))),
('flags', c_int),
('app_data', POINTER(c_ubyte)),
('rsa_sign', CFUNCTYPE(c_int, POINTER(c_ubyte), c_uint, POINTER(c_ubyte), c_uint, POINTER(RSA))),
('rsa_verify', CFUNCTYPE(c_int, POINTER(c_ubyte), c_uint, POINTER(c_ubyte), c_uint, POINTER(RSA))),
]
'''
struct rsa_st
{
/* The first parameter is used to pickup errors where
* this is passed instead of aEVP_PKEY, it is set to 0 */
int pad;
long version;
const RSA_METHOD *meth;
/* functional reference if 'meth' is ENGINE-provided */
ENGINE *engine;
BIGNUM *n;
BIGNUM *e;
BIGNUM *d;
BIGNUM *p;
BIGNUM *q;
BIGNUM *dmp1;
BIGNUM *dmq1;
BIGNUM *iqmp;
/* be careful using this if the RSA structure is shared */
CRYPTO_EX_DATA ex_data;
int references;
int flags;
/* Used to cache montgomery values */
BN_MONT_CTX *_method_mod_n;
BN_MONT_CTX *_method_mod_p;
BN_MONT_CTX *_method_mod_q;
/* all BIGNUM values are actually in the following data, if it is not
* NULL */
char *bignum_data;
BN_BLINDING *blinding;
BN_BLINDING *mt_blinding;
};
'''
RSA._fields_ = [
('pad', c_int),
('version', c_long),
('meth', POINTER(RSA_METHOD)),
('engine', POINTER(ENGINE)),
('n', POINTER(BIGNUM)),
('e', POINTER(BIGNUM)),
('d', POINTER(BIGNUM)),
('p', POINTER(BIGNUM)),
('q', POINTER(BIGNUM)),
('dmp1', POINTER(BIGNUM)),
('dmq1', POINTER(BIGNUM)),
('iqmp', POINTER(BIGNUM)),
('ex_data', POINTER(CRYPTO_EX_DATA)),
('references', c_int),
('flags', c_int),
('_method_mod_n', POINTER(BN_MONT_CTX)),
('_method_mod_p', POINTER(BN_MONT_CTX)),
('_method_mod_q', POINTER(BN_MONT_CTX)),
('bignum_data', c_ubyte),
('blinding', POINTER(BN_BLINDING)),
('mt_blinding', POINTER(BN_BLINDING)),
]
После вызывается собственно RSA_public_encrypt, в который нужно передать два буфера - unsigned char *from и unsigned char *to, которые содержат исходное сообщение и буфер, куда запишется шифрованное. Функция же возвращает -1, т.е. произошла ошибка :( Не знаю в чем проблема, наверное неправильно определяю эти буферы
Вот код:
openssl = CDLL('E:\workspace\\dll\libeay32.dll')
generate_key = openssl.RSA_generate_key
generate_key.restype = POINTER(RSA)
a = generate_key(c_int(256), c_ulong(RSA_F4), None, None)
print(openssl.RSA_check_key(a)) #тут выводит 1 - ок
#from_buf = POINTER(c_ubyte)
from_buf = (c_ubyte * 6)(81, 119, 101, 114, 116, 121) #'это строка 'Qwerty'
#to_buf = POINTER(c_ubyte)
to_buf = (c_ubyte * 50)()
#from_buf = c_wchar_p('Qwerty') #пробовал и так обяъвлять, и через create_string_buffer
#to_buf = c_wchar_p('')
print(openssl.RSA_public_encrypt(c_int(7), from_buf, to_buf, a, c_int(RSA_NO_PADDING))) # а вот тут -1. Ппробовал оборачивать буферы в byref и pointer - ничего :(