使用LuaJit进行FFI加密/解密

马特·J

我正在尝试通过LuaJIT中的FFI使用OpenSSL进行加密和解密-我尝试了很多不同的变体,但运气不高。我的代码似乎总是返回空字符串。

我正在尝试遵循作为OpenSSL文档的一部分描述的模式:https : //www.openssl.org/docs/manmaster/crypto/EVP_PKEY_decrypt.html

    local ffi = require "ffi"
    ffi.cdef[[
      EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e);
      void *malloc(size_t size);
      void free(void *ptr);

      int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx);
      int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen);

      int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx);
      int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen);
    ]]

    local s = "hello world"
    local s_len = #s
    local out_len1 = ffi.new("size_t[1]")

    local ctx = ffi.C.EVP_PKEY_CTX_new(gen_key, nil)
    if not ctx then
      return nil
    end

    if ffi.C.EVP_PKEY_encrypt_init(ctx) == 0 then
      return nil
    end

    if ffi.C.EVP_PKEY_encrypt(ctx, nil, out_len1, s, s_len) == 0 then
      return nil
    end

    local buf = ffi.new("unsigned char[?]", out_len1[0])

    if ffi.C.EVP_PKEY_encrypt(ctx, buf, out_len1, s, s_len) == 0 then
      return nil
    end

    local s = ffi.string(buf, out_len1[0])
    local s_len = #s
    local out_len2 = ffi.new("size_t[1]")

    if ffi.C.EVP_PKEY_decrypt_init(ctx) == 0 then
      return nil
    end

    if ffi.C.EVP_PKEY_decrypt(ctx, nil, out_len2, s, s_len) == 0 then
      return nil
    end

    local buf = ffi.new("unsigned char[?]", out_len2[0])
    if ffi.C.EVP_PKEY_decrypt(ctx, buf, out_len2, s, s_len) == 0 then
      return nil
    end

    return ffi.string(buf, out_len2[0])
马特·J

回答我自己的问题。

我的原始代码没有严格遵循OpenSSL的C实现示例,因为它只能获得加密数据的长度。它还从未使用任何填充,它重用了变量,并且没有拆分为方法,并且故意遗漏了一些依赖关系以隐藏一些实现细节。

现在,以下代码可以(独立)运行并具有更好的结构,但有意不进行错误检查,并且与内容的争执时间超过(KeyLength-42)。

为了提供一些上下文,此代码需要使用PEM格式的证书和密钥:

local ffi = require "ffi"
local ssl = ffi.load "ssl"

ffi.cdef[[
  typedef struct bio_st BIO;
  typedef struct bio_method_st BIO_METHOD;
  BIO *BIO_new(BIO_METHOD *type);
  BIO *BIO_new_mem_buf(void *buf, int len);
  typedef struct evp_pkey_ctx_st EVP_PKEY_CTX;
  typedef struct evp_pkey_st EVP_PKEY;
  typedef struct engine_st ENGINE;
  EVP_PKEY *EVP_PKEY_new(void);
  void EVP_PKEY_free(EVP_PKEY *key);
  typedef struct rsa_st RSA;
  typedef int pem_password_cb(char *buf, int size, int rwflag, void *userdata);
  RSA * PEM_read_bio_RSAPrivateKey(BIO *bp, RSA **rsa, pem_password_cb *cb, void *u);
  int EVP_PKEY_set1_RSA(EVP_PKEY *pkey,RSA *key);
  EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e);
  int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, int p1, void *p2);
  typedef struct x509_st X509;
  X509 *PEM_read_bio_X509(BIO *bp, X509 **x, pem_password_cb *cb, void *u);
  EVP_PKEY * X509_get_pubkey(X509 *x);
  void X509_free(X509 *a);
  int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx);
  int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen);
  int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx);
  int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen);
]]

function encrypt(publicPEM, body)
  local bioIn = ffi.new("unsigned char[?]", #publicPEM)
  ffi.copy(bioIn, publicPEM, #publicPEM)
  local bio = ffi.C.BIO_new_mem_buf(bioIn, -1)
  local x509 = ffi.C.PEM_read_bio_X509(bio, nil, nil, nil)
  ffi.gc(x509, ffi.C.X509_free)
  local pKey = ffi.C.X509_get_pubkey(x509)
  local ctx = ffi.C.EVP_PKEY_CTX_new(pKey, nil)
  ffi.C.EVP_PKEY_encrypt_init(ctx)

  -- Adds OEAP padding
  ffi.C.EVP_PKEY_CTX_ctrl(ctx, 6, -1, 4097, 4, null)

  -- Get the length
  local outputLength = ffi.new("size_t[1]")
  ffi.C.EVP_PKEY_encrypt(ctx, nil, outputLength, body, #body)

  -- Encrypt into outputBuffer
  local outputBuffer = ffi.new("unsigned char[?]", outputLength[0])
  ffi.C.EVP_PKEY_encrypt(ctx, outputBuffer, outputLength, body, #body)

  -- Turn it into a string
  return ffi.string(outputBuffer, outputLength[0])
end

function decrypt(privatePEM, body)
  local bioIn = ffi.new("unsigned char[?]", #privatePEM)
  ffi.copy(bioIn, privatePEM, #privatePEM)
  local bio = ffi.C.BIO_new_mem_buf(bioIn, -1)
  if not bio then
    return nil
  end
  local rsa = ffi.C.PEM_read_bio_RSAPrivateKey(bio, nil, nil, nil)
  local pKey = ffi.C.EVP_PKEY_new()

  ffi.C.EVP_PKEY_set1_RSA(pKey, rsa)
  ctx = ffi.C.EVP_PKEY_CTX_new(pKey, nil)
  ffi.C.EVP_PKEY_decrypt_init(ctx)

  -- Adds OEAP padding
  ffi.C.EVP_PKEY_CTX_ctrl(ctx, 6, -1, 4097, 4, null)

  -- Get the length
  local outputLength = ffi.new("size_t[1]")
  ffi.C.EVP_PKEY_decrypt(ctx, nil, outputLength, body, #body)

  -- Decrypt into outputBuffer
  local outputBuffer = ffi.new("unsigned char[?]", outputLength[0])
  ffi.C.EVP_PKEY_decrypt(ctx, outputBuffer, outputLength, body, #body)

  -- Turn it into a string
  return ffi.string(outputBuffer, outputLength[0])
end

io.write("Result: "..tostring(decrypt([[-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCoOeFfldK3bcsun1klFb+d3egSKkfq3oFAf6n6hQ2R3TrzY3Bb
+4hYSr5LhrP/HYOvc7bxk+T3GQe6C8B/7aOYJQ+DOweKoNK90uVEQRtFO8EZ4Z7r
JfaS2rhPuX71AnfwuvNG/TZ5UFruvwUqvs2hzw57gl+IzFgAtG8rtVX/zwIDAQAB
AoGAEeGFGRndue2LqTr6yLxVD7ykjDm+RzK7XlWzhZNa6+Qt/ezV5pEH3wqiy3hX
7Yf/lUiha3Ai6Dja32WcYnyp5Lf9vvxMcdyMlv3r78N7KUccXo6qvh0dE5VdrNxH
4U5oDs5U4OXaTC3/pCgBCV9w7IxbrLvsj1yKYQ7QBOLnJTECQQDQuHo6e1C2miyI
VZv5YzTdXucpshAhpDNf65Z214e/Ww1OOFNOw9sBaGGyOVv+F9EfHC8kO4pA32S7
HOx+knRlAkEAzlUpafetWL+Ht6yguyc9yBbfeoFL6v576GpMjkIV7w1oqmiDa5ep
P71U1evgYAwH6X0ZcnPXZwZU7eOkBZdeIwJBAKG2nPUcwC+KioBjHAMAa2As/Jug
m8EE8M0bwit32HRZfpihKWK4esG/dxpYOL9JArzA4IGJJBgZPXl/8ngqzsUCQQCy
Z1xJrcgKxoC4xeCsMf/vdCeDKyzTYXsNuGu9TVLdwcBQJ9IKQ7Yp0LD7ztnQ8lYd
AvfvyE3lXMoubvgxhXH1AkBDTjC3cHtlXygZcrqviIq/lOblm2voR2YW520079Yd
h0u2xcG80J53NkBk/q0IaTOamESi1IrD2ds3xp5mZulI
-----END RSA PRIVATE KEY-----
]], encrypt([[-----BEGIN CERTIFICATE-----
MIICYTCCAcoCCQCT+Ubn23B63TANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJV
UzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEN
MAsGA1UEChMES29uZzEWMBQGA1UECxMNSVQgRGVwYXJ0bWVudDESMBAGA1UEAxMJ
bG9jYWxob3N0MB4XDTE2MDExODEwNDUyOVoXDTE3MDExNzEwNDUyOVowdTELMAkG
A1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFu
Y2lzY28xDTALBgNVBAoTBEtvbmcxFjAUBgNVBAsTDUlUIERlcGFydG1lbnQxEjAQ
BgNVBAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqDnh
X5XSt23LLp9ZJRW/nd3oEipH6t6BQH+p+oUNkd0682NwW/uIWEq+S4az/x2Dr3O2
8ZPk9xkHugvAf+2jmCUPgzsHiqDSvdLlREEbRTvBGeGe6yX2ktq4T7l+9QJ38Lrz
Rv02eVBa7r8FKr7Noc8Oe4JfiMxYALRvK7VV/88CAwEAATANBgkqhkiG9w0BAQUF
AAOBgQAEC5ugqY6rOd3BbIam172OVQQwxcVx8BVfuiqX0zsFdBwTm/AvvdyJXRwo
64AqEIanvJF8Htq3Q9As6PNgHJ4eWEAZYTKlsf0PRM+d1T/uce3HY2SePuwr1Kqx
gFQjYTabjv361j8X3zB3HwrGsuED2UXxerXczszyiQNv/6BQlg==
-----END CERTIFICATE-----
]], "hello world"))).."\n")

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用ZipArchive类进行加密/解密

来自分类Dev

使用AES算法进行加密和解密

来自分类Dev

使用Java进行AES加密和解密

来自分类Dev

使用C ++进行加密和解密

来自分类Dev

使用SIP TLS进行加密/解密

来自分类Dev

使用Spring Security进行AES加密/解密

来自分类Dev

使用phpseclib使用AES进行加密,并使用CryptoJS进行解密

来自分类Dev

使用jsencrypt进行RSA加密,使用弹性城堡进行解密?

来自分类Dev

只需使用Javascript进行XOR加密并使用Java进行解密

来自分类Dev

使用Java进行RSA加密并使用JavaScript进行解密

来自分类Dev

使用CryptoJS进行AES加密并使用CodeIgniter进行解密

来自分类Dev

在C#中使用MachineKey进行加密和解密

来自分类Dev

使用C#中的证书进行加密和解密

来自分类Dev

使用CryptoJS在javascript中进行AES加密/解密

来自分类Dev

使用C#进行SQL Server加密/解密

来自分类Dev

Laravel使用C#进行加密和解密

来自分类Dev

使用OpenSSL进行AES_128_CBC加密/解密

来自分类Dev

使用JS和PHP进行RSA加密和解密

来自分类Dev

使用CryptoJS在javascript中进行AES加密/解密

来自分类Dev

使用Java NetBeans对图像进行rsa加密和解密

来自分类Dev

使用RSA和AES进行加密/解密;标准?

来自分类Dev

使用mcrypt加密/解密

来自分类Dev

自己进行加密/解密-系统

来自分类Dev

使用Talend Data Integration对.properties文件中的密码进行加密/加密和解密

来自分类Dev

如何使用phpseclib进行加密和使用AES算法使用Java进行解密

来自分类Dev

RSA使用Pycrypto OAEP进行加密,并使用普通的旧Java进行解密

来自分类Dev

使用IOS进行公钥加密和使用C#进行解密

来自分类Dev

使用C#对其进行加密,然后使用Android对其进行解密(AES | IllegalBlockSizeException)

来自分类Dev

使用IOS进行公钥加密和使用C#进行解密

Related 相关文章

  1. 1

    使用ZipArchive类进行加密/解密

  2. 2

    使用AES算法进行加密和解密

  3. 3

    使用Java进行AES加密和解密

  4. 4

    使用C ++进行加密和解密

  5. 5

    使用SIP TLS进行加密/解密

  6. 6

    使用Spring Security进行AES加密/解密

  7. 7

    使用phpseclib使用AES进行加密,并使用CryptoJS进行解密

  8. 8

    使用jsencrypt进行RSA加密,使用弹性城堡进行解密?

  9. 9

    只需使用Javascript进行XOR加密并使用Java进行解密

  10. 10

    使用Java进行RSA加密并使用JavaScript进行解密

  11. 11

    使用CryptoJS进行AES加密并使用CodeIgniter进行解密

  12. 12

    在C#中使用MachineKey进行加密和解密

  13. 13

    使用C#中的证书进行加密和解密

  14. 14

    使用CryptoJS在javascript中进行AES加密/解密

  15. 15

    使用C#进行SQL Server加密/解密

  16. 16

    Laravel使用C#进行加密和解密

  17. 17

    使用OpenSSL进行AES_128_CBC加密/解密

  18. 18

    使用JS和PHP进行RSA加密和解密

  19. 19

    使用CryptoJS在javascript中进行AES加密/解密

  20. 20

    使用Java NetBeans对图像进行rsa加密和解密

  21. 21

    使用RSA和AES进行加密/解密;标准?

  22. 22

    使用mcrypt加密/解密

  23. 23

    自己进行加密/解密-系统

  24. 24

    使用Talend Data Integration对.properties文件中的密码进行加密/加密和解密

  25. 25

    如何使用phpseclib进行加密和使用AES算法使用Java进行解密

  26. 26

    RSA使用Pycrypto OAEP进行加密,并使用普通的旧Java进行解密

  27. 27

    使用IOS进行公钥加密和使用C#进行解密

  28. 28

    使用C#对其进行加密,然后使用Android对其进行解密(AES | IllegalBlockSizeException)

  29. 29

    使用IOS进行公钥加密和使用C#进行解密

热门标签

归档