天天看點

Python 進行RSA私鑰加密,公鑰解密

使用M2Crypto庫

需要安裝M2Crypto庫

  1. # -*- coding: UTF-8 -*-
  2. import M2Crypto
  3. from Crypto.PublicKey import RSA
  4. import base64
  5. import sys
  6. #私鑰加密,公鑰解密
  7. def pri_encrypt(msg, file_name):
  8. rsa_pri = M2Crypto.RSA.load_key(file_name)
  9. ctxt_pri = rsa_pri.private_encrypt(msg, M2Crypto.RSA.pkcs1_padding) #這裡的方法選擇加密填充方式,是以在解密的時候 要對應。
  10. ctxt64_pri = ctxt_pri.encode('base64') #密文是base64 友善儲存 encode成str
  11. print ('密文:%s'% ctxt64_pri)
  12. return ctxt64_pri
  13. def pub_decrypt_with_pubkeyfile(msg, file_name):
  14. rsa_pub = M2Crypto.RSA.load_pub_key(file_name)
  15. pub_decrypt(msg, rsa_pub)
  16. def pub_decrypt_with_pubkeystr(msg, pub_key):
  17. #将pub_key轉成bio對象,再将bio對象轉換成公鑰對象
  18. bio = M2Crypto.BIO.MemoryBuffer(pub_key)
  19. rsa_pub = M2Crypto.RSA.load_pub_key_bio(bio)
  20. pub_decrypt(msg, rsa_pub)
  21. def pub_decrypt(msg, rsa_pub):
  22. ctxt_pri = msg.decode("base64") # 先将str轉成base64
  23. maxlength = 128
  24. output = ''
  25. while ctxt_pri:
  26. input = ctxt_pri[:128]
  27. ctxt_pri = ctxt_pri[128:]
  28. out = rsa_pub.public_decrypt(input, M2Crypto.RSA.pkcs1_padding) #解密
  29. output = output + out
  30. print('明文:%s'% output)
  31. if __name__ == "__main__":
  32. prikey_file = './rsa/rsa_private_key.pem'
  33. pubkey_file = './rsa/rsa_public_key.pem'
  34. msg = 'Test String.'
  35. primsg = pri_encrypt(msg, prikey_file)
  36. pub_decrypt(primsg, pubkey_file)

使用C語言的動态庫

decrypt.c

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <ctype.h>
  5. #include <openssl/rsa.h>
  6. #include <openssl/engine.h>
  7. void decrypt(char *pristr, char *pubkey, int padding, char *pub_str)
  8. {
  9. BIO *bp;
  10. EVP_PKEY *pkey;
  11. int crypted_len, n;
  12. size_t data_len;
  13. char *data, *dest_p, *p, *last, *decrypt_buf, *dest;
  14. char buf[128];
  15. bp = BIO_new_mem_buf((void *)pubkey, -1);
  16. pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL);
  17. BIO_free(bp);
  18. if (!pkey) {
  19. fprintf(stderr, "get public key error\n");
  20. return;
  21. }
  22. crypted_len = EVP_PKEY_size(pkey);
  23. decrypt_buf = malloc(crypted_len + 1);
  24. if (!decrypt_buf) {
  25. fprintf(stderr, "decrypt_buf, malloc error\n");
  26. return;
  27. }
  28. base64_decode(pristr, (unsigned char **)&data, &data_len);
  29. dest = malloc(data_len);
  30. if (!dest) {
  31. fprintf(stderr, "dest, malloc error\n");
  32. free(decrypt_buf);
  33. return;
  34. }
  35. dest_p = dest;
  36. p = data;
  37. last = data + data_len;
  38. do {
  39. n = last - p;
  40. if (n > 128) {
  41. n = 128;
  42. }
  43. bzero(buf, sizeof(buf));
  44. bzero(decrypt_buf, sizeof(decrypt_buf));
  45. memcpy(buf, p, n);
  46. p += n;
  47. crypted_len = RSA_public_decrypt(n, (unsigned char *)buf, decrypt_buf, pkey->pkey.rsa, padding);
  48. if (crypted_len != -1) {
  49. memcpy(dest_p, decrypt_buf, crypted_len);
  50. dest_p += crypted_len;
  51. }
  52. } while (last - p > 0);
  53. *dest_p = 0;
  54. strcpy(pub_str, dest);
  55. free(decrypt_buf);
  56. free(dest);
  57. free(data);
  58. }
  59. size_t calc_decode_len(const char* b64input) {
  60. size_t len = strlen(b64input), padding = 0;
  61. if (b64input[len - 1] == '=' && b64input[len - 2] == '=') {
  62. padding = 2;
  63. } else if (b64input[len - 1] == '=') {
  64. padding = 1;
  65. }
  66. return (size_t) len * 0.75 - padding;
  67. }
  68. int base64_decode(char *b64message, unsigned char **buffer, size_t *len) {
  69. BIO *bio, *b64;
  70. int decode_len = calc_decode_len(b64message);
  71. *buffer = malloc(decode_len);
  72. if (!*buffer) {
  73. fprintf(stderr, "buffer, malloc error\n");
  74. return -1;
  75. }
  76. bio = BIO_new_mem_buf(b64message, -1);
  77. b64 = BIO_new(BIO_f_base64());
  78. bio = BIO_push(b64, bio);
  79. BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
  80. *len = BIO_read(bio, *buffer, strlen(b64message));
  81. BIO_free_all(bio);
  82. if (*len != decode_len) {
  83. return -1;
  84. }
  85. return 0;
  86. }

decrypt.h

  1. #ifndef __DECRYPT_H__
  2. #define __DECRYPT_H__
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <ctype.h>
  7. #include <openssl/rsa.h>
  8. #include <openssl/engine.h>
  9. void decrypt(char* pristr, char* pubkey, int padding, char* pubstr);
  10. #endif

編譯,生成一個動态庫檔案

  1. gcc -Wall -fpic -shared -lcrypto decrypt.c -o libdec.so

寫一個測試檔案進行測試,main.c

  1. #include "decrypt.h"
  2. #include <stdio.h>
  3. int main()
  4. {
  5. //公鑰
  6. char *pkey_str = "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2kcrRvxURhFijDoPpqZ/IgPlA\ngppkKrek6wSrua1zBiGTwHI2f+YCa5vC1JEiIi9uw4srS0OSCB6kY3bP2DGJagBo\nEgj/rYAGjtYJxJrEiTxVs5/GfPuQBYmU0XAtPXFzciZy446VPJLHMPnmTALmIOR5\nDddd1Zklod9IQBMjjwIDAQAB\n-----END PUBLIC KEY-----";
  7. //用私鑰加密過的字元串
  8. char *pri_str = "YFSGlJTpNYakrZuZqZ55dcA5mVUb/JQBr3hdDjODsAVSdoVVytIagk9Wt0CD/uX+7jGL9pqev8/u0I0ZBKEmz5huXp8TdZSnskCZ7GTeHNW0VPJcW8OcBxAValA0jQSv2mBP+tc1r6mdvf66GEzhvgBfTnp3Sp7V3dijJ9bNstIDyrGm/BlByhcMr3UqXjTFJaui6t5TxvZhCuSV9sg+xVVA+sR3uFI78b5lKomg5Vu31EBZvXASlFfaOc4StltRUH2aSiRqjnbXe8dlRZO0Ih44htYs2QfehzeQnPHtTwNHUvtVIVcIdI/7j9yfy5es13QeIgfKghY/ENUnB2V7iA==";
  9. char decrypted_buf[10240];
  10. decrypt(pri_str, pkey_str, 1, decrypted_buf);
  11. printf("%s", decrypted_buf);
  12. return 0;
  13. }

編譯,測試:

  1. export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:'pwd'
  2. gcc main.c -o test -L./ -ldec
  3. ./test
  4. [[email protected] so_test]${"order_id_com":"2013061805870589","amount":"0.10","account":"test","order_id":"2013061800002115","result":"success","user_id":"0"}

在python中使用libdec.so 

注意,需要安裝cffi,然後用pypy運作 

test.py

  1. import os
  2. from cffi import FFI
  3. path = os.path.split(os.path.realpath(__file__))[0]
  4. ffi = FFI()
  5. #引入動态庫
  6. lib = ffi.dlopen(path + "/libdec.so")
  7. print('Loaded lib {0}'.format(lib))
  8. #函數聲明,類似于C的.h檔案
  9. ffi.cdef(
  10. '''
  11. void decrypt(char* pristr, char* pubkey, int padding, char* pubstr);
  12. int printf(const char* format, ...);
  13. '''
  14. )
  15. #公鑰
  16. pkey_str = '''-----BEGIN PUBLIC KEY-----
  17. MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2kcrRvxURhFijDoPpqZ/IgPlA
  18. gppkKrek6wSrua1zBiGTwHI2f+YCa5vC1JEiIi9uw4srS0OSCB6kY3bP2DGJagBo
  19. Egj/rYAGjtYJxJrEiTxVs5/GfPuQBYmU0XAtPXFzciZy446VPJLHMPnmTALmIOR5
  20. Dddd1Zklod9IQBMjjwIDAQAB
  21. -----END PUBLIC KEY-----'''
  22. #用私鑰加密過的字元串
  23. pri_str = "klzAd6Qu87M/0GdkmmeJbyk/NKuIIRS/M/4GpckMNfe4jwjBc9w38LExpYVvJZ5RKkr2y9Wuj6cZsThqAM0ZDcFZ2Ew2csRZlMnc9kD/yqHHMb0fb6KL3g7DZ3sRAhAIT2MkTDHOVKctxrc5Qcn8Ie2IX1Xgz7G+yvn0j1VYc3xGUbbCxxPjb3MTuDUDFbElPNq98dQufrcFUBsXwVdQJv6+GwE+7N/IJffPA6TNv3aB+AUe7sc/lbKOywxCSb0+rxPkb0mcT6q5O0S1bRIvZqtxQJn0HydqmFYPBYr9X2lzkgGIwZL8oX6vb2YVNHRPoCxKh+10TewAOOlUggbTfA=="
  24. #申請C風格的數組
  25. pub_str = ffi.new("char[]", 10240)
  26. lib.decrypt(pri_str, pkey_str, 1, pub_str)
  27. print pub_str
  28. lib.printf("%s\n", pub_str)
  29. #轉換成Python可用的字元串
  30. pystr = ffi.string(pub_str)
  31. print pystr