1.python中公钥加密的方式是OAEP,代码如下:
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
filename = toolname + '_' + key
register_file_path = os.path.join(app_path,'static','register',filename+'.crt')
public_filepath = os.path.join(app_path,'static','public_key',toolname+'.pem')
f = open(public_filepath, 'rb')
key_public = RSA.importKey(f.read())
f.close()
encryptor = PKCS1_OAEP.new(key_public)
key_en = encryptor.encrypt(bytes(key,encoding='utf8'))
print ('key_en',key_en)
f1 = open(register_file_path, 'wb')
f1.write(key_en)
f1.close
2.在python中生成了公钥和私钥文件,然后在c++中进行私钥解密,在运行代码之前需要利用openssl库,网上有一个编译openssl源码的教程,但是感觉有一丝丝麻烦,放弃。根据文章https://blog.csdn.net/sxm0403/article/details/82796838中安装openssl 建议选择win32版本,程序通用性强,选择非light版本。安装,有个lib位置选项,选在system那个选项比较好。按章完成之后记得修改项目工程的项目属性:vs2013:配置属性–VC++目录–包含目录,添加openssl下的include文件夹; 链接器–常规–附加库目录,添加openssl下的lib和bin。好下边上代码
#include "stdafx.h"
#include <bitset>
#include <iostream>
#include <fstream>
#include<openssl/rsa.h>
#include<openssl/pem.h>
#include<openssl/err.h>
#include<openssl/applink.c>
using namespace std;
#pragma comment(lib, "libcrypto.lib")
#define PRIVATEKEY "nmap.pem"
#define PASS "8888" //口令
int main(int argc, _TCHAR* argv[])
{
unsigned char key[1024];
unsigned char decrypted[4098] ="";
RSA *privateRsa = NULL;
FILE *fp = NULL;
BIO * key1 = NULL;
key1 = BIO_new(BIO_s_file());
BIO_read_filename(key1, "nmap.pem ");
privateRsa = PEM_read_bio_RSAPrivateKey(key1, NULL, NULL, NULL);
BIO_free_all(key1);
ifstream in("nmap.crt", ios::in | ios::binary);
if (!in){
cerr << "文件打开失败" << endl;
exit(-1);
}
in.read((char *)&key, sizeof(key)); //一直读到文件结束
int readedBytes = in.gcount(); //看刚才读了多少字节
key[readedBytes] = '\0';
in.close();
int rsa_len = RSA_size(privateRsa);
unsigned char *decryptMsg = (unsigned char *)malloc(rsa_len);
memset(decryptMsg, 0, rsa_len);
int num = RSA_private_decrypt(rsa_len, key, decryptMsg, privateRsa, RSA_PKCS1_OAEP_PADDING);//私钥长度,加密的信息,解密的信息,私钥,
RSA_free(privateRsa);
if (num>0){
return 1;
}
cout << "Hello world!" << decryptMsg << endl;
return 0;
}
代码中需要注意的是lib的引用 #pragma comment(lib, “libcrypto.lib”) 现在好多的代码时
#pragma comment(lib, “libeay32.lib”) 会发现自己下载安装的文件夹中并没有这个lib文件,查阅相关资料得出libeay32.libl-> libcrypto.lib ssleay32.lib-> libssl.lib。
好了基本上c++利用已知的私钥文件进行解密就是这样了。
3.后来用c#试了一版利用已知私钥文件进行解密,代码量时真的多相对于c++,不过还好网上人才辈出,有许多网上前辈都已经总结了经验。来,走起
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Security.Cryptography;
using System.IO;
using System.Net;
namespace toolui
{
public partial class Form1 : Form
{
string privfile;
string registerfile;
public Form1()
{
InitializeComponent();
}
private void label1_Click(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
string key = textBox1.Text;
FileStream fs = new FileStream(registerfile, FileMode.Open);
long size = fs.Length;
byte[] encryptedData = new byte[size];
fs.Read(encryptedData, 0, encryptedData.Length);
fs.Close();
string priKey = System.IO.File.ReadAllText(privfile);
priKey = priKey.Replace("-----BEGIN RSA PRIVATE KEY-----", "")
.Replace("-----END RSA PRIVATE KEY-----", "");
string str_prvkey = PrivateKeyDecXml(priKey);
byte[] s = Decrypt(encryptedData,str_prvkey, true);
string result = System.Text.Encoding.Default.GetString(s);
if (result == key)
{
string filename = Path.GetFileNameWithoutExtension(registerfile);
string url = string.Format("http://127.0.0.1:5000/register/uuid?filename={0}", filename);
string resstr = HttpGet(url);
MessageBox.Show(resstr);
}
else {
MessageBox.Show("请输入正确的key值","提示" );
}
}
byte[] Decrypt(byte[] data, string privatekey, bool fOAEP)
{
byte[] decryptedData;
using (RSACryptoServiceProvider rSACryptoServiceProvider = new RSACryptoServiceProvider())
{
rSACryptoServiceProvider.FromXmlString(privatekey);
decryptedData = rSACryptoServiceProvider.Decrypt(data, fOAEP);
}
return decryptedData;
}
private static int GetIntegerSize(BinaryReader binr)
{
int count;
var bt = binr.ReadByte();
if (bt != 0x02) //expect integer
return 0;
bt = binr.ReadByte();
if (bt == 0x81)
count = binr.ReadByte(); // data size in next byte
else
if (bt == 0x82)
{
var highbyte = binr.ReadByte();
var lowbyte = binr.ReadByte();
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
count = BitConverter.ToInt32(modint, 0);
}
else
{
count = bt; // we already have the data size
}
while (binr.ReadByte() == 0x00)
{ //remove high order zeros in data
count -= 1;
}
binr.BaseStream.Seek(-1, SeekOrigin.Current); //last ReadByte wasn't a removed zero, so back up a byte
return count;
}
public static RSACryptoServiceProvider DecodeRsaPrivateKey(string priKey)
{
var privkey = Convert.FromBase64String(priKey);
MemoryStream mem = new MemoryStream(privkey);
byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
//FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
try
{
var twobytes = binr.ReadUInt16();
if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8230)
binr.ReadInt16(); //advance 2 bytes
else
return null;
twobytes = binr.ReadUInt16();
if (twobytes != 0x0102) //version number
return null;
var bt = binr.ReadByte();
if (bt != 0x00)
return null;
var elems = GetIntegerSize(binr);
MODULUS = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
E = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
D = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
P = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
Q = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
DP = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
DQ = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
IQ = binr.ReadBytes(elems);
// ------- create RSACryptoServiceProvider instance and initialize with public key -----
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
RSAParameters rsAparams = new RSAParameters();
rsAparams.Modulus = MODULUS;
rsAparams.Exponent = E;
rsAparams.D = D;
rsAparams.P = P;
rsAparams.Q = Q;
rsAparams.DP = DP;
rsAparams.DQ = DQ;
rsAparams.InverseQ = IQ;
rsa.ImportParameters(rsAparams);
return rsa;
}
catch (Exception e)
{
Console.WriteLine(e.Message + e.StackTrace);
return null;
}
finally
{
binr.Close();
}
}
public static string PrivateKeyDecXml(string priKey)
{
RSACryptoServiceProvider rsaProvider = DecodeRsaPrivateKey(priKey);
var privateKey = rsaProvider.ToXmlString(true);
return privateKey;
}
public static string RsaDecrypt(string privatekey, string content)
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
byte[] cipherbytes;
rsa.FromXmlString(privatekey);
cipherbytes = rsa.Decrypt(Convert.FromBase64String(content), true);
return Encoding.UTF8.GetString(cipherbytes);
}
public string HttpGet(string Url)//发送GET请求
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
request.Method = "GET";
request.ContentType = "text/html;charset=UTF-8";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream myResponseStream = response.GetResponseStream();
StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.UTF8);
string retString = myStreamReader.ReadToEnd();
myStreamReader.Close();
myResponseStream.Close();
return retString;
}
private void button3_Click(object sender, EventArgs e)
{
//选择证书文件 就是私钥文件
OpenFileDialog dialog = new OpenFileDialog();
dialog.Multiselect = false;
dialog.Title = "请选择证书文件";
dialog.Filter = "所有文件(*.*)|*.*|证书文件(*.pem*)|*.pem*";
if(dialog.ShowDialog()==System.Windows.Forms.DialogResult.OK)
{
privfile = dialog.FileName;
textBox2.Text = privfile;
}
}
private void button2_Click(object sender, EventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.Multiselect = false;
dialog.Title = "请选择证书文件";
dialog.Filter = "所有文件(*.*)|*.*|注册文件(*.crt*)|*.crt*";
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
registerfile = dialog.FileName;
textBox3.Text = registerfile;
}
}
}
}
好了,基本上是这样了 如果想要利用现成的私钥解密函数首先需要将从文件中读入的私钥转化为c#中能够识别的私钥。当时转化的代码时参考这篇文章的,解密完之后需要根据解析的结果向flask发送一个请求。参考的时这篇文章中的post和get函数。
4.其中用到的小tips:
格式化输出:
int a = 12345678;
Label1.Text = string.Format(“asdfadsf{0}adsfasdf”,a);
获取文件夹路径以及文件夹路径下的文件名称
class Program
{
static void Main(string[] args)
{
//获取当前运行程序的目录
string fileDir = Environment.CurrentDirectory;
Console.WriteLine("当前程序目录:"+fileDir);
//一个文件目录
string filePath = "C:\\JiYF\\BenXH\\BenXHCMS.xml";
Console.WriteLine("该文件的目录:"+filePath);
string str = "获取文件的全路径:" + Path.GetFullPath(filePath); //-->C:\JiYF\BenXH\BenXHCMS.xml
Console.WriteLine(str);
str = "获取文件所在的目录:" + Path.GetDirectoryName(filePath); //-->C:\JiYF\BenXH
Console.WriteLine(str);
str = "获取文件的名称含有后缀:" + Path.GetFileName(filePath); //-->BenXHCMS.xml
Console.WriteLine(str);
str = "获取文件的名称没有后缀:" + Path.GetFileNameWithoutExtension(filePath); //-->BenXHCMS
Console.WriteLine(str);
str = "获取路径的后缀扩展名称:" + Path.GetExtension(filePath); //-->.xml
Console.WriteLine(str);
str = "获取路径的根目录:" + Path.GetPathRoot(filePath); //-->C:\
Console.WriteLine(str);
Console.ReadKey();
}
}
打开文件夹以及文件
OpenFileDialog dialog = new OpenFileDialog();
dialog.Multiselect = false;
dialog.Title = "请选择证书文件";
dialog.Filter = "所有文件(*.*)|*.*|注册文件(*.crt*)|*.crt*";
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
registerfile = dialog.FileName;
textBox3.Text = registerfile;
}
python 中删除某个文件:
import os
os.remove(path)
C# byte[]与string的相互转换
byte[]转string:
string str = System.Text.Encoding.Default.GetString( byteArray );
string转byte[]:
byte[] byteArray = System.Text.Encoding.Default.GetBytes( str );
ASCII byte[]转string:
string str = System.Text.Encoding.ASCII.GetString ( byteArray );
string转ASCII byte[]:
byte[] byteArray = System.Text.Encoding.ASCII.GetBytes ( str );
c#读取文件为字符串
string text = System.IO.File.ReadAllText(@"C:\Users\Public\TestFolder\WriteText.txt");
c#读取文件为字节
FileStream fs = new FileStream(registerfile, FileMode.Open);
long size = fs.Length;
byte[] encryptedData = new byte[size];
fs.Read(encryptedData, 0, encryptedData.Length);
C#中在路径前加 @ 的作用
不转译 \