If you call a method that will return a string, you will need to call the free_string method to stop this .dll from leaking memory!
cargo build --target=i686-pc-windows-msvc --release
Output file: .\target\i686-pc-windows-msvc\release\rhttp.dll
cargo build --target=x86_64-pc-windows-msvc --release
Output file: .\target\x86_64-pc-windows-msvc\release\rhttp.dll
> python3 .\test.py --dll .\target\x86_64-pc-windows-msvc\release\rhttp.dll
True
True
True
OK
True
True
fn base64_decode(s: *const c_char) -> *mut c_char {}
fn base64_encode(s: *const c_char) -> *mut c_char {}
Correct usage in python:
lib.base64_encode.argtypes = (c_void_p, )
lib.base64_encode.restype = c_void_p
lib.base64_decode.argtypes = (c_void_p, )
lib.base64_decode.restype = c_void_p
def base64_encode(text):
res = ""
ptr1 = lib.base64_encode(text.encode('utf-8'))
try:
res = ctypes.cast(ptr1, ctypes.c_char_p).value.decode('utf-8')
finally:
lib.free_string(ptr1)
return res
def base64_decode(text):
res = ""
ptr1 = lib.base64_decode(text.encode('utf-8'))
try:
res = ctypes.cast(ptr1, ctypes.c_char_p).value.decode('utf-8')
finally:
lib.free_string(ptr1)
return res
print(base64_encode('Nunc suscipit libero velit, ut venenatis dui aliquet eu.'))
print(base64_decode('TnVuYyBzdXNjaXBpdCBsaWJlcm8gdmVsaXQsIHV0IHZlbmVuYXRpcyBkdWkgYWxpcXVldCBldS4='))
fn gzip_base64_decode(s: *const c_char) -> *mut c_char {}
fn gzip_base64_encode(s: *const c_char) -> *mut c_char {}
Correct usage in python:
lib.gzip_base64_encode.argtypes = (c_void_p, )
lib.gzip_base64_encode.restype = c_void_p
lib.gzip_base64_decode.argtypes = (c_void_p, )
lib.gzip_base64_decode.restype = c_void_p
def gzip_base64_encode(text):
res = ""
ptr1 = lib.gzip_base64_encode(text.encode('utf-8'))
try:
res = ctypes.cast(ptr1, ctypes.c_char_p).value.decode('utf-8')
finally:
lib.free_string(ptr1)
return res
def gzip_base64_decode(text):
res = ""
ptr1 = lib.gzip_base64_decode(text.encode('utf-8'))
try:
res = ctypes.cast(ptr1, ctypes.c_char_p).value.decode('utf-8')
finally:
lib.free_string(ptr1)
return res
print(gzip_base64_encode('abc' * 10000))
print(gzip_base64_encode('Nunc suscipit libero velit, ut venenatis dui aliquet eu.'))
print(gzip_base64_decode('H4sIABd1DGAAAw3GyQ2AQAwDwFZcAKIUeliWPCxF4YhN/fCbzTXR7smLQnKP58QbSS2wflXUEBuHiZG8HUJ4/QBu/ZCdOAAAAA=='))
fn sha512_hash(s: *const c_char) -> *mut c_char {}
Correct usage in python:
lib.sha512_hash.argtypes = (c_void_p, )
lib.sha512_hash.restype = c_void_p
def sha512(text, expected):
ptr1 = lib.sha512_hash(text.encode('utf-8'))
try:
hashed = ctypes.cast(ptr1, ctypes.c_char_p).value.decode('utf-8')
if hashed == expected:
return True
return (hashed == expected, hashed, expected)
finally:
lib.free_string(ptr1)
print(sha512("mysecret", "7b6f7690ae2a5ecdf66b3db2adf91340a680da1ab82561796b8504db942476967369814aa35050dd86838848c1ba703450f2f5e21b0a8e4cff690b855ae5bd8c"))
fn sha3_512_hash(s: *const c_char) -> *mut c_char {}
Correct usage in python:
lib.sha3_512_hash.argtypes = (c_void_p, )
lib.sha3_512_hash.restype = c_void_p
def sha3_512(text, expected):
ptr1 = lib.sha3_512_hash(text.encode('utf-8'))
try:
hashed = ctypes.cast(ptr1, ctypes.c_char_p).value.decode('utf-8')
if hashed == expected:
return True
return (hashed == expected, hashed, expected)
finally:
lib.free_string(ptr1)
print(sha3_512("mysecret", "ef846feafed891792553756277b48e90784eca281f683920551f36b359833b10aab4897765050e398232e3f213fe49c7c50271f339d4797c25dc58c3d7f33f81"))
aes_encrypt
and aes_decrypt
are used to encrypt and decrypt messages via using AES-128 block cipher in ECB mode and with PKCS#7 padding.
Both method works primarily on byte arrays which you can provide as plain text
, hexadecimal representation
and base64 encoding
. These can be configured by setting the plans as designed:
Flags can be provided as a 32-bit integer (for compatibility reasons), which then will be converted into an unsigned integer. These flags can be combined, but some combinations will be ignored:
- 0x01 - Input is provided as
hexadecimal representation
- 0x02 - Input is provided using
base64 encoding
- 0x04 - Output should be returned in a
hexadecimal representation
- 0x08 - Output should be returned using
base64 encoding
- 0x10 - Key is provided as
hexadecimal representation
- 0x20 - Key is provided using
base64 encoding
fn aes_encrypt(c_plaintext: *const c_char, c_key: *const c_char, flags: i32) -> *mut c_char {}
fn aes_decrypt(c_ciphertext: *const c_char, c_key: *const c_char, flags: i32) -> *mut c_char {}
Correct usage in python:
lib.aes_encrypt.argtypes = (c_void_p, c_void_p, c_int32, )
lib.aes_encrypt.restype = c_void_p
lib.aes_decrypt.argtypes = (c_void_p, c_void_p, c_int32, )
lib.aes_decrypt.restype = c_void_p
def aes_encrypt(plaintext, key, flags, expected):
ptr1 = lib.aes_encrypt(plaintext.encode('utf-8'), key.encode('utf-8'), flags)
try:
response = ctypes.cast(ptr1, ctypes.c_char_p).value.decode('utf-8')
if response == expected:
return True
return response
finally:
lib.free_string(ptr1)
def aes_decrypt(ciphertext, key, flags, expected):
ptr1 = lib.aes_decrypt(ciphertext.encode('utf-8'), key.encode('utf-8'), flags)
try:
response = ctypes.cast(ptr1, ctypes.c_char_p).value.decode('utf-8')
if response == expected:
return True
return response
finally:
lib.free_string(ptr1)
print(aes_encrypt("hello", "000102030405060708090a0b0c0d0e0f", 0x18, 'XYdJ4q91MbK/ZmHp5drwEg=='))
print(aes_decrypt("XYdJ4q91MbK/ZmHp5drwEg==", "000102030405060708090a0b0c0d0e0f", 0x12, 'hello'))
fn get_plain(c_url: *const c_char, code_ref: &mut i32) -> *mut c_char {}
fn get_xml(c_url: *const c_char, code_ref: &mut i32) -> *mut c_char {}
fn get_json(c_url: *const c_char, code_ref: &mut i32) -> *mut c_char {}
Correct usage in python:
lib.get_plain.argtypes = (c_void_p, POINTER(c_int32), )
lib.get_plain.restype = c_void_p
def get_plain(url):
c = c_int32(0)
ptr1 = lib.get_plain(url.encode('utf-8'), byref(c))
try:
content = ctypes.cast(ptr1, ctypes.c_char_p).value.decode('utf-8')
return (c.value, content)
finally:
lib.free_string(ptr1)
print(get("https://api-test.onlineszamla.nav.gov.hu/"))
get_plain
, get_xml
, get_json
only differ in the headers sent along with the request.
fn post_plain(c_url: *const c_char, c_body: *const c_char, code_ref: &mut i32) -> *mut c_char {}
Correct usage in python:
lib.post_xml.argtypes = (c_void_p, c_void_p, POINTER(c_int32), )
lib.post_xml.restype = c_void_p
def post_xml(url, body):
c = c_int32(0)
ptr1 = lib.post_xml(url.encode('utf-8'), body.encode('utf-8'), byref(c))
try:
content = ctypes.cast(ptr1, ctypes.c_char_p).value.decode('utf-8')
return (c.value, content)
finally:
lib.free_string(ptr1)
print(post_xml("https://example.com/tokenExchange", 'field1=value1&field2=value2'))
fn post_xml(c_url: *const c_char, c_body: *const c_char, code_ref: &mut i32) -> *mut c_char {}
Correct usage in python:
lib.post_xml.argtypes = (c_void_p, c_void_p, POINTER(c_int32), )
lib.post_xml.restype = c_void_p
def post_xml(url, body):
c = c_int32(0)
ptr1 = lib.post_xml(url.encode('utf-8'), body.encode('utf-8'), byref(c))
try:
content = ctypes.cast(ptr1, ctypes.c_char_p).value.decode('utf-8')
return (c.value, content)
finally:
lib.free_string(ptr1)
print(post_xml("https://example.com/xmlEndpoint", '<?xml version="1.0" ?></xml>'))
fn post_json(c_url: *const c_char, c_body: *const c_char, code_ref: &mut i32) -> *mut c_char {}
Correct usage in python:
lib.post_json.argtypes = (c_void_p, c_void_p, POINTER(c_int32), )
lib.post_json.restype = c_void_p
def post_json(url, body):
c = c_int32(0)
ptr1 = lib.post_json(url.encode('utf-8'), body.encode('utf-8'), byref(c))
try:
content = ctypes.cast(ptr1, ctypes.c_char_p).value.decode('utf-8')
return (c.value, content)
finally:
lib.free_string(ptr1)
print(post_json("https://example.com/jsonEndpoint", '{}'))