使用M2Crypto庫
需要安裝M2Crypto庫
- # -*- coding: UTF-8 -*-
- import M2Crypto
- from Crypto.PublicKey import RSA
- import base64
- import sys
-
- #私鑰加密,公鑰解密
- def pri_encrypt(msg, file_name):
- rsa_pri = M2Crypto.RSA.load_key(file_name)
- ctxt_pri = rsa_pri.private_encrypt(msg, M2Crypto.RSA.pkcs1_padding) #這裡的方法選擇加密填充方式,是以在解密的時候 要對應。
- ctxt64_pri = ctxt_pri.encode('base64') #密文是base64 友善儲存 encode成str
- print ('密文:%s'% ctxt64_pri)
- return ctxt64_pri
-
- def pub_decrypt_with_pubkeyfile(msg, file_name):
- rsa_pub = M2Crypto.RSA.load_pub_key(file_name)
- pub_decrypt(msg, rsa_pub)
-
- def pub_decrypt_with_pubkeystr(msg, pub_key):
- #将pub_key轉成bio對象,再将bio對象轉換成公鑰對象
- bio = M2Crypto.BIO.MemoryBuffer(pub_key)
- rsa_pub = M2Crypto.RSA.load_pub_key_bio(bio)
- pub_decrypt(msg, rsa_pub)
-
- def pub_decrypt(msg, rsa_pub):
- ctxt_pri = msg.decode("base64") # 先将str轉成base64
- maxlength = 128
- output = ''
- while ctxt_pri:
- input = ctxt_pri[:128]
- ctxt_pri = ctxt_pri[128:]
- out = rsa_pub.public_decrypt(input, M2Crypto.RSA.pkcs1_padding) #解密
- output = output + out
- print('明文:%s'% output)
-
- if __name__ == "__main__":
- prikey_file = './rsa/rsa_private_key.pem'
- pubkey_file = './rsa/rsa_public_key.pem'
- msg = 'Test String.'
- primsg = pri_encrypt(msg, prikey_file)
- pub_decrypt(primsg, pubkey_file)
使用C語言的動态庫
decrypt.c
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <openssl/rsa.h>
- #include <openssl/engine.h>
-
- void decrypt(char *pristr, char *pubkey, int padding, char *pub_str)
- {
- BIO *bp;
- EVP_PKEY *pkey;
- int crypted_len, n;
- size_t data_len;
- char *data, *dest_p, *p, *last, *decrypt_buf, *dest;
- char buf[128];
-
- bp = BIO_new_mem_buf((void *)pubkey, -1);
- pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL);
- BIO_free(bp);
-
- if (!pkey) {
- fprintf(stderr, "get public key error\n");
- return;
- }
-
- crypted_len = EVP_PKEY_size(pkey);
- decrypt_buf = malloc(crypted_len + 1);
- if (!decrypt_buf) {
- fprintf(stderr, "decrypt_buf, malloc error\n");
- return;
- }
-
- base64_decode(pristr, (unsigned char **)&data, &data_len);
-
- dest = malloc(data_len);
- if (!dest) {
- fprintf(stderr, "dest, malloc error\n");
- free(decrypt_buf);
- return;
- }
- dest_p = dest;
-
- p = data;
- last = data + data_len;
-
- do {
- n = last - p;
- if (n > 128) {
- n = 128;
- }
-
- bzero(buf, sizeof(buf));
- bzero(decrypt_buf, sizeof(decrypt_buf));
- memcpy(buf, p, n);
- p += n;
-
- crypted_len = RSA_public_decrypt(n, (unsigned char *)buf, decrypt_buf, pkey->pkey.rsa, padding);
- if (crypted_len != -1) {
- memcpy(dest_p, decrypt_buf, crypted_len);
- dest_p += crypted_len;
- }
- } while (last - p > 0);
-
- *dest_p = 0;
- strcpy(pub_str, dest);
- free(decrypt_buf);
- free(dest);
- free(data);
- }
-
-
- size_t calc_decode_len(const char* b64input) {
- size_t len = strlen(b64input), padding = 0;
-
- if (b64input[len - 1] == '=' && b64input[len - 2] == '=') {
- padding = 2;
- } else if (b64input[len - 1] == '=') {
- padding = 1;
- }
-
- return (size_t) len * 0.75 - padding;
- }
-
- int base64_decode(char *b64message, unsigned char **buffer, size_t *len) {
- BIO *bio, *b64;
-
- int decode_len = calc_decode_len(b64message);
- *buffer = malloc(decode_len);
- if (!*buffer) {
- fprintf(stderr, "buffer, malloc error\n");
- return -1;
- }
-
- bio = BIO_new_mem_buf(b64message, -1);
- b64 = BIO_new(BIO_f_base64());
- bio = BIO_push(b64, bio);
-
- BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
- *len = BIO_read(bio, *buffer, strlen(b64message));
- BIO_free_all(bio);
-
- if (*len != decode_len) {
- return -1;
- }
-
- return 0;
- }
decrypt.h
- #ifndef __DECRYPT_H__
- #define __DECRYPT_H__
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <openssl/rsa.h>
- #include <openssl/engine.h>
-
- void decrypt(char* pristr, char* pubkey, int padding, char* pubstr);
-
- #endif
編譯,生成一個動态庫檔案
- gcc -Wall -fpic -shared -lcrypto decrypt.c -o libdec.so
寫一個測試檔案進行測試,main.c
- #include "decrypt.h"
- #include <stdio.h>
-
- int main()
- {
- //公鑰
- char *pkey_str = "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2kcrRvxURhFijDoPpqZ/IgPlA\ngppkKrek6wSrua1zBiGTwHI2f+YCa5vC1JEiIi9uw4srS0OSCB6kY3bP2DGJagBo\nEgj/rYAGjtYJxJrEiTxVs5/GfPuQBYmU0XAtPXFzciZy446VPJLHMPnmTALmIOR5\nDddd1Zklod9IQBMjjwIDAQAB\n-----END PUBLIC KEY-----";
-
- //用私鑰加密過的字元串
- char *pri_str = "YFSGlJTpNYakrZuZqZ55dcA5mVUb/JQBr3hdDjODsAVSdoVVytIagk9Wt0CD/uX+7jGL9pqev8/u0I0ZBKEmz5huXp8TdZSnskCZ7GTeHNW0VPJcW8OcBxAValA0jQSv2mBP+tc1r6mdvf66GEzhvgBfTnp3Sp7V3dijJ9bNstIDyrGm/BlByhcMr3UqXjTFJaui6t5TxvZhCuSV9sg+xVVA+sR3uFI78b5lKomg5Vu31EBZvXASlFfaOc4StltRUH2aSiRqjnbXe8dlRZO0Ih44htYs2QfehzeQnPHtTwNHUvtVIVcIdI/7j9yfy5es13QeIgfKghY/ENUnB2V7iA==";
-
- char decrypted_buf[10240];
- decrypt(pri_str, pkey_str, 1, decrypted_buf);
- printf("%s", decrypted_buf);
- return 0;
- }
編譯,測試:
- export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:'pwd'
- gcc main.c -o test -L./ -ldec
- ./test
- [[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
- import os
- from cffi import FFI
- path = os.path.split(os.path.realpath(__file__))[0]
- ffi = FFI()
- #引入動态庫
- lib = ffi.dlopen(path + "/libdec.so")
- print('Loaded lib {0}'.format(lib))
- #函數聲明,類似于C的.h檔案
- ffi.cdef(
- '''
- void decrypt(char* pristr, char* pubkey, int padding, char* pubstr);
- int printf(const char* format, ...);
- '''
- )
- #公鑰
- pkey_str = '''-----BEGIN PUBLIC KEY-----
- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2kcrRvxURhFijDoPpqZ/IgPlA
- gppkKrek6wSrua1zBiGTwHI2f+YCa5vC1JEiIi9uw4srS0OSCB6kY3bP2DGJagBo
- Egj/rYAGjtYJxJrEiTxVs5/GfPuQBYmU0XAtPXFzciZy446VPJLHMPnmTALmIOR5
- Dddd1Zklod9IQBMjjwIDAQAB
- -----END PUBLIC KEY-----'''
-
- #用私鑰加密過的字元串
- pri_str = "klzAd6Qu87M/0GdkmmeJbyk/NKuIIRS/M/4GpckMNfe4jwjBc9w38LExpYVvJZ5RKkr2y9Wuj6cZsThqAM0ZDcFZ2Ew2csRZlMnc9kD/yqHHMb0fb6KL3g7DZ3sRAhAIT2MkTDHOVKctxrc5Qcn8Ie2IX1Xgz7G+yvn0j1VYc3xGUbbCxxPjb3MTuDUDFbElPNq98dQufrcFUBsXwVdQJv6+GwE+7N/IJffPA6TNv3aB+AUe7sc/lbKOywxCSb0+rxPkb0mcT6q5O0S1bRIvZqtxQJn0HydqmFYPBYr9X2lzkgGIwZL8oX6vb2YVNHRPoCxKh+10TewAOOlUggbTfA=="
-
- #申請C風格的數組
- pub_str = ffi.new("char[]", 10240)
- lib.decrypt(pri_str, pkey_str, 1, pub_str)
-
- print pub_str
- lib.printf("%s\n", pub_str)
-
- #轉換成Python可用的字元串
- pystr = ffi.string(pub_str)
- print pystr