2022-01-30 19:10:42 +01:00
|
|
|
module rsa
|
|
|
|
|
2022-02-02 11:05:49 +01:00
|
|
|
import net.openssl
|
2022-01-30 19:10:42 +01:00
|
|
|
|
|
|
|
pub struct RSAInstance {
|
|
|
|
pair &C.RSA
|
|
|
|
pub:
|
|
|
|
public_key []byte
|
|
|
|
private_key []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn gen_key_pair(len int, exp int) ?RSAInstance {
|
2022-02-02 11:05:49 +01:00
|
|
|
assert openssl.is_used == 1
|
2022-01-30 19:10:42 +01:00
|
|
|
rsa := C.RSA_new()
|
|
|
|
bn := C.BN_new()
|
|
|
|
|
|
|
|
C.BN_set_word(bn, exp)
|
|
|
|
|
|
|
|
if C.RAND_status() != 1 {
|
|
|
|
return error('Not seeded')
|
|
|
|
}
|
|
|
|
|
|
|
|
res := C.RSA_generate_key_ex(rsa, len, bn, voidptr(0))
|
|
|
|
C.BN_free(bn)
|
|
|
|
|
|
|
|
if res != 1 {
|
|
|
|
err := []byte{len: 256}
|
|
|
|
C.ERR_error_string(C.ERR_get_error(), err.data)
|
|
|
|
return error(err.bytestr())
|
|
|
|
}
|
|
|
|
|
|
|
|
private := C.BIO_new(C.BIO_s_mem())
|
|
|
|
public := C.BIO_new(C.BIO_s_mem())
|
|
|
|
|
|
|
|
C.PEM_write_bio_RSAPrivateKey(private, rsa, voidptr(0), voidptr(0), 0, voidptr(0),
|
|
|
|
voidptr(0))
|
|
|
|
C.PEM_write_bio_RSAPublicKey(public, rsa)
|
|
|
|
|
|
|
|
private_len := C.BIO_pending(private)
|
|
|
|
public_len := C.BIO_pending(public)
|
|
|
|
|
|
|
|
private_key := []byte{len: private_len}
|
|
|
|
public_key := []byte{len: public_len}
|
|
|
|
|
|
|
|
C.BIO_read(private, private_key.data, private_len)
|
|
|
|
C.BIO_read(public, public_key.data, public_len)
|
|
|
|
|
|
|
|
return RSAInstance{
|
|
|
|
pair: rsa
|
|
|
|
public_key: public_key
|
|
|
|
private_key: private_key
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn (rsa RSAInstance) encrypt(msg []byte) ?([]byte, int) {
|
|
|
|
res := []byte{len: C.RSA_size(rsa.pair)}
|
|
|
|
len := C.RSA_public_encrypt(msg.len, msg.data, res.data, rsa.pair, C.RSA_PKCS1_OAEP_PADDING)
|
|
|
|
if len == -1 {
|
|
|
|
err := []byte{len: 256}
|
|
|
|
C.ERR_error_string(C.ERR_get_error(), err.data)
|
|
|
|
return error(err.bytestr())
|
|
|
|
}
|
|
|
|
return res, len
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn (rsa RSAInstance) decrypt(len int, data []byte) ?[]byte {
|
|
|
|
res := []byte{len: len}
|
|
|
|
l := C.RSA_private_decrypt(len, data.data, res.data, rsa.pair, C.RSA_PKCS1_OAEP_PADDING)
|
|
|
|
if l == -1 {
|
|
|
|
err := []byte{len: 256}
|
|
|
|
C.ERR_error_string(C.ERR_get_error(), err.data)
|
|
|
|
return error(err.bytestr())
|
|
|
|
}
|
|
|
|
return res[0..l]
|
|
|
|
}
|