好久没写博客了,正好趁着实现网络工程与安全的DES算法的功夫,把代码发上来。

  DES的介绍可见:DES加密

  原理不赘述了。。实在太多,其实就是一个形式化算法,按部就班的实现就可以,只不过有些繁琐,我写了3个晚上 = =。

  主要实现了利用DES算法对一个文本文档加密,然后再将其内容解密。

程序截图

  明文和密钥

  加密然后解密

  密文和解密后文本

代码

 //该程序实现了文本文档的DES加密和解密。

 #include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std; //IP置换表
char IP[] = {
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,}; //IP^-1 置换表
char IP_1[] = {
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,}; //扩展置换表E
int E[] = {, , , , , ,
, , , , , ,
, ,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,, }; //置换函数P
int P[] = {,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,}; //S盒
int S[][][] ={
{{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,}}, {{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,}}, {{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,}}, {{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,}}, {{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,}}, {{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,}}, {{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,}}, {{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,}}};
//置换选择1
int PC_1[] = {,,,,,,,
,,,,,,,
,,,,,,,
,,,,,,,
,,,,,,,
,,,,,,,
,,,,,,,
,,,,,,}; //置换选择2
int PC_2[] = {,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,}; //对左移次数的规定
int LS[] = {,,,,,,,,,,,,,,,,}; //存放子密钥
unsigned __int64 K[]; //将含64个二进制字符的字符串转换为二进制形式存储在long long int中
unsigned __int64 str2bit(unsigned char s[])
{
unsigned __int64 bin = ;
int i;
for(i=;i<;i++){
bin = bin<< | (s[i]-''); //s[i]>>j & 1 表示取s[i]的第j位
}
return bin;
} //将含8位字符串转换为二进制形式存储在long long int中,例ABCDEFGH转换为64位二进制数
unsigned __int64 bstr2bit(unsigned char s[])
{
unsigned __int64 bin = ;
int i,j;
for(i=;i<;i++){
for(j=;j<;j++){
bin = bin | ( (unsigned __int64)((s[i]>>j)%) << (j+*(-i)) ); //将s[i]的第j位(低位开始)取出放到bin的对应位置
}
}
return bin;
} //将 unsigned __int64 形式的按十六进制串输出(64位有效的二进制数串)
void DisplayHex64(unsigned __int64 bin)
{
int i,t=;
for(i=;i>=;i--){
t = t<< | ((bin>>i) & );
if(i%==){
if(<=t && t<=)
printf("%d",t);
else if(<=t && t<=)
printf("%c",+t-);
t=;
}
if(i%==)
printf(" ");
}
printf("\n");
}
//将 unsigned __int64 形式的按十六进制串输出(48位有效的二进制数串)
void DisplayHex48(unsigned __int64 bin)
{
int i,t=;
for(i=;i>=;i--){
t = t<< | ((bin>>i) & );
if(i%==){
if(<=t && t<=)
printf("%d",t);
else if(<=t && t<=)
printf("%c",+t-);
t=;
}
if(i%==)
printf(" ");
}
printf("\n");
}
//将 unsigned __int64 形式的按十六进制串输出(32位有效的二进制数串)
void DisplayHex32(unsigned __int64 bin)
{
int i,t=;
for(i=;i>=;i--){
t = t<< | ((bin>>i) & );
if(i%==){
if(<=t && t<=)
printf("%d",t);
else if(<=t && t<=)
printf("%c",+t-);
t=;
}
if(i%==)
printf(" ");
}
printf("\n");
}
//将 unsigned __int64 形式的按十六进制串输出(28位有效的二进制数串)
void DisplayHex28(unsigned __int64 bin)
{
int i,t=;
for(i=;i>=;i--){
t = t<< | ((bin>>i) & );
if(i%==){
if(<=t && t<=)
printf("%d",t);
else if(<=t && t<=)
printf("%c",+t-);
t=;
}
if(i%==)
printf(" ");
}
printf("\n");
} //将 unsigned __int64 形式的二进制串和十六进制输出(64位有效的二进制数串)
void DisplayBin64(unsigned __int64 bin)
{
int i;
for(i=;i>=;i--){
printf("%d",(bin>>i) %);
}
printf("\n");
DisplayHex64(bin);
} //将 unsigned __int64 形式的二进制串和十六进制输出(48位有效的二进制数串)
void DisplayBin48(unsigned __int64 bin)
{
int i;
for(i=;i>=;i--){
printf("%d",(bin>>i) %);
}
printf("\n");
DisplayHex48(bin);
} //将 unsigned __int64 形式的二进制串和十六进制输出(32位有效的二进制数串)
void DisplayBin32(unsigned __int64 bin)
{
int i;
for(i=;i>=;i--){
printf("%d",(bin>>i) %);
}
printf("\n");
DisplayHex32(bin);
} //将 unsigned __int64 形式的二进制串和十六进制输出(28位有效的二进制数串)
void DisplayBin28(unsigned __int64 bin)
{
int i;
for(i=;i>=;i--){
printf("%d",(bin>>i) %);
}
printf("\n");
DisplayHex28(bin);
} /* ------------------------------ 【1】初始置换IP ------------------------------
* 把明文顺序打乱重新排列,置换输出为64位,
* 数据置换后的第一位,第二位分别是原来的58、50位
*/ unsigned __int64 InitReplace(unsigned __int64 bin) //初始置换IP
{
unsigned __int64 t = ;
int i;
for(i=;i<;i++){
t = t | ( (bin>>(-IP[i])) %) << (-i);
}
return t;
} /* ------------------------------ 【2】将置换输出的64位数据分成左右两半 ------------------------------
* 左一半称为L0,右一半称为R0,各32位。
*/ void DivideLR(unsigned __int64 binip,unsigned __int64 &L0,unsigned __int64 &R0) //将置换输出的64位数据分为L0(32位),R0(32位)两部分
{
unsigned __int64 one = ;
L0 = binip >> ;
R0 = binip % (one<<);
} /* ------------------------------ 【3】计算函数的16轮迭代 ------------------------------
* 1~16轮加密迭代
*/ //置换选择1,64->56
unsigned __int64 FunPC_1(unsigned __int64 bink)
{
unsigned __int64 binpc_1 = ;
int i;
for(i=;i<;i++)
binpc_1 |= ( (bink>>(-PC_1[i])) %) << (-i);
return binpc_1;
} //获得第i轮C,D,即Ci-1,Di-1 ==> Ci,Di
void getNextCD(int i,unsigned __int64 &C,unsigned __int64 &D)
{
unsigned __int64 t=,one=;
t = C >> (-LS[i]);
C = (C<<LS[i])%(one<<);
C |= t;
t = D >> (-LS[i]);
D = (D<<LS[i])%(one<<);
D |= t;
} //置换选择2,56->48
unsigned __int64 FunPC_2(unsigned __int64 t)
{
//获得子密钥k
unsigned __int64 k=;
int i;
for(i=;i<;i++)
k |= ( (t>>(-PC_2[i])) %) << (-i);
return k;
} //子密钥生成
void ProduceK(unsigned __int64 bink)
{
unsigned __int64 binpc_1,one=,C=,D=;
binpc_1 = FunPC_1(bink); //置换选择1 //分成2个28位
C = binpc_1 >> ;
D = binpc_1 % (one << ); int i;
for(i=;i<=;i++){
//确定子密钥K[i]
getNextCD(i,C,D);
printf("第%d轮:\n",i);
printf("C[%d] = ",i);
DisplayBin28(C);
printf("D[%d] = ",i);
DisplayBin28(D);
printf("\n"); unsigned __int64 t=;
t = ((C<<) | D)%(one<<);
K[i] = FunPC_2(t); //进行置换选择2,将56位->48位子密钥
}
} //扩展置换E,32->48
unsigned __int64 FunE(unsigned __int64 R)
{
unsigned __int64 t = ;
int i;
for(i=;i<;i++)
t |= ( (R>>(-E[i])) %) << (-i);
return t;
} //S盒代换
unsigned __int64 FunS(unsigned __int64 RX)
{
int x,y,i;
unsigned __int64 one = ,t,RS = ;
for(i=;i<;i++){
t = ( RX >> (*(-i)) ) % (one<<);
x = t>>;
x = (x<<) | (t%);
y = (t<<)%(one<<)>>;
RS = RS<< | S[i][x][y];
}
return RS;
} //置换P运算
unsigned __int64 FunP(unsigned __int64 RS)
{
unsigned __int64 RP = ;
int i;
for(i=;i<;i++)
RP |= ( (RS>>(-P[i])) %) << (-i);
return RP;
} //轮函数f(R,K)
unsigned __int64 f(int i,unsigned __int64 R,unsigned __int64 k)
{
unsigned __int64 RE,RX,RS,RP;
RE = FunE(R); //将32位Ri-1扩展置换为48位
RX = RE ^ k; //将48位RE与子密钥k异或运算
RS = FunS(RX); //S盒代换
RP = FunP(RS); //置换P运算
return RP;
} unsigned __int64 Iteration16(unsigned __int64 L0,unsigned __int64 R0) //进行16次迭代计算
{
int i;
unsigned __int64 Ri = R0;
unsigned __int64 Li = L0;
printf("L0=");
DisplayBin32(L0);
printf("R0=");
DisplayBin32(R0);
printf("\n");
for(i=;i<=;i++){
printf("第%d轮加密:\n",i);
unsigned __int64 t = Ri; //轮函数
Ri = f(i,Ri,K[i]);
printf("f(R%d,K%d)=",i-,i);
DisplayBin32(Ri); //Li-1和轮函数结果异或运算得到Ri
Ri = Li ^ Ri;
//轮函数运算结果即是Li
Li = t; //输出Li和Ri
printf("L%d=",i);
DisplayBin32(Li);
printf("R%d=",i);
DisplayBin32(Ri);
printf("\n");
} return Ri<< | Li;
} unsigned __int64 InverseIteration16(unsigned __int64 L0,unsigned __int64 R0) //进行逆16次迭代计算,为解密过程
{
int i;
unsigned __int64 Ri = R0;
unsigned __int64 Li = L0;
printf("L0=");
DisplayBin32(L0);
printf("R0=");
DisplayBin32(R0);
printf("\n");
for(i=;i>=;i--){
printf("第%d轮加密:\n",-i);
unsigned __int64 t = Ri; //轮函数
Ri = f(i,Ri,K[i]);
printf("f(R%d,K%d)=",i-,i);
DisplayBin32(Ri); //Li-1和轮函数结果异或运算得到Ri
Ri = Li ^ Ri;
//轮函数运算结果即是Li
Li = t; //输出Li和Ri
printf("L%d=",i);
DisplayBin32(Li);
printf("R%d=",i);
DisplayBin32(Ri);
printf("\n");
} return Ri<< | Li;
} /* ------------------------------ 【4】逆初始置换IP^-1 ------------------------------
* 把数据打乱重排,产生64位密文。
*/ unsigned __int64 InverseInitReplace(unsigned __int64 bin) //进行逆初始置换IP^-1
{
unsigned __int64 t = ;
int i;
for(i=;i<;i++){
t = t | ( (bin>>(-IP_1[i])) %) << (-i);
}
return t;
} void printOut(FILE* fo,unsigned __int64 bin)
{
char ans[]={},t=;
int i,cnt=;
for(i=;i>=;i--){
t = t<< | ((bin>>i)%);
if(i%==){
ans[cnt++] = t;
t = ;
}
}
fwrite(ans,,,fo);
} //加密函数
void Encryption()
{
//文件读入
FILE* fm = fopen(".\\Plaintext.txt","rb"); //明文文件
FILE* fk = fopen(".\\key.txt","r"); //密钥文件
FILE* fo = fopen(".\\Ciphertext.txt","wb"); //密文文件 if(fm==NULL){
printf("明文文件input.txt打开失败\n");
}
if(fk==NULL){
printf("密钥文件key.txt打开失败\n");
}
if(fo==NULL){
printf("加密后文件output.txt打开失败\n");
} unsigned char s[]={},key[]={};
int i; fscanf(fk,"%s",key); //读取密钥 while(fread(s,,,fm)){
printf("----------------------------------------------------------------------------\n");
printf("\n");
printf("当前读取的明文串为:\n");
printf("%s\n",s);
unsigned __int64 bin = bstr2bit(s); //将加密串转换为2进制形式
printf("\n");
unsigned __int64 bink = str2bit(key); //将密钥串转换为2进制形式
printf("\n"); //输出
printf("\n");
printf("【输入】\n");
printf("输入的二进制明文串:\n");
DisplayBin64(bin);
printf("输入的二进制密钥串:\n");
DisplayBin64(bink);
printf("\n"); //IP置换
printf("明文初始化置换后:\n");
unsigned __int64 binip = InitReplace(bin);
DisplayBin64(binip);
printf("\n"); //获得L0,R0
printf("将明文分割为L0,R0两部分:\n");
unsigned __int64 L0,R0;
DivideLR(binip,L0,R0); //将binip分割为L0和R0
//输出L0,R0
printf("L0为:");
DisplayBin32(L0);
printf("R0为:");
DisplayBin32(R0);
printf("\n"); //生成16个子密钥,并输出
printf("--------------- 子密钥生成过程 ---------------\n");
memset(K,,sizeof(K));
ProduceK(bink);
printf("生成的16个子密钥:\n");
for(i=;i<=;i++){
printf("K[%d]为 ",i);
DisplayBin48(K[i]);
//printf("\n");
}
printf("\n"); //16次加密迭代
printf("--------------- 16轮加密迭代 --------------- \n");
unsigned __int64 binIter = Iteration16(L0,R0);
printf("迭代加密后的结果:\n");
DisplayBin64(binIter);
printf("\n"); //逆初始置换IP_1
unsigned __int64 binip_1 = InverseInitReplace(binIter);
printf("最后,逆初始置换:\n");
DisplayBin64(binip_1);
printf("\n"); //输出最终加密结果
printf("【加密结果】\n明文 \"%s\" 的DES加密的结果为:\n",s);
DisplayBin64(binip_1); printf("\n");
printf("----------------------------------------------------------------------------\n");
printf("\n"); //将加密结果写到加密文件中
printOut(fo,binip_1); memset(s,,sizeof(s));
}
//文件关闭
fclose(fm);
fclose(fk);
fclose(fo);
} //解密函数
void Decryption()
{
//文件读入
FILE* fm = fopen(".\\Ciphertext.txt","rb"); //密文文件
FILE* fk = fopen(".\\key.txt","r"); //密钥文件
FILE* fo = fopen(".\\DecrypPlaintext.txt","wb"); //解密后文件 if(fm==NULL){
printf("密文文件 Ciphertext.txt 打开失败\n");
}
if(fk==NULL){
printf("密钥文件 key.txt 打开失败\n");
}
if(fo==NULL){
printf("解密后文件 DecrypPlaintext.txt 打开失败\n");
} unsigned char s[]={},key[]={};
int i; fscanf(fk,"%s",key); //读取密钥 while(fread(s,,,fm)){
printf("----------------------------------------------------------------------------\n");
printf("\n");
printf("当前读取的密文串为:\n");
printf("%s\n",s);
unsigned __int64 bin = bstr2bit(s); //将密文串转换为2进制形式
printf("\n");
unsigned __int64 bink = str2bit(key); //将密钥串转换为2进制形式
printf("\n"); //输出
printf("----------------------------------------------------------------------------\n");
printf("\n");
printf("【输入】\n");
printf("输入的二进制密文串:\n");
DisplayBin64(bin);
printf("输入的二进制密钥串:\n");
DisplayBin64(bink);
printf("\n"); //IP置换
printf("密文初始化置换后:\n");
unsigned __int64 binip = InitReplace(bin);
DisplayBin64(binip);
printf("\n"); //获得L0,R0
printf("将密文分割为L0,R0两部分:\n");
unsigned __int64 L0,R0;
DivideLR(binip,L0,R0); //将binip分割为L0和R0
//输出L0,R0
printf("L0为:");
DisplayBin32(L0);
printf("R0为:");
DisplayBin32(R0);
printf("\n"); //生成16个子密钥,并输出
printf("--------------- 子密钥生成过程 ---------------\n");
memset(K,,sizeof(K));
ProduceK(bink);
printf("生成的16个子密钥:\n");
for(i=;i<=;i++){
printf("K[%d]为 ",i);
DisplayBin48(K[i]);
//printf("\n");
}
printf("\n"); //16次加密迭代
printf("--------------- 16轮加密迭代 --------------- \n");
unsigned __int64 binIter = InverseIteration16(L0,R0);
printf("迭代解密后的结果:\n");
DisplayBin64(binIter);
printf("\n"); //逆初始置换IP_1
unsigned __int64 binip_1 = InverseInitReplace(binIter);
printf("最后,逆初始置换:\n");
DisplayBin64(binip_1);
printf("\n"); //输出最终加密结果
printf("【解密结果】\n密文 \"%s\" 的DES解密的结果为:\n",s);
DisplayBin64(binip_1); printf("\n");
printf("----------------------------------------------------------------------------\n"); //将加密结果写到加密文件中
printOut(fo,binip_1); memset(s,,sizeof(s));
}
//文件关闭
fclose(fm);
fclose(fk);
fclose(fo);
} int Menu(int &Case)
{
int in; FILE* fk = fopen(".\\key.txt","r"); //密钥文件
if(fk==NULL){
printf("密钥文件key.txt打开失败\n");
} unsigned char key[];
fscanf(fk,"%s",key); //读取密钥
unsigned __int64 bink = str2bit(key); //将密钥串转换为2进制形式
printf("【%d】当前密钥(key)为:(二进制形式)\n",Case++);
DisplayBin64(bink);
printf("(密钥存储在 key.txt 中)\n");
printf("\n"); printf("请选择,是使用DES算法加密还是解密?\n");
printf("(加密过程:Plaintext.txt => Ciphertext.txt\n");
printf(" 解密过程:Ciphertext.txt => DecrypPlaintext.txt )\n");
printf("[1] 加密\n");
printf("[2] 解密\n");
printf("[0] 退出程序\n"); scanf("%d",&in);
getchar();
fflush(stdin); // 清空缓冲区 if(in== || in== || in==){
return in;
}
else{
printf("输入错误,请重新输入!\n");
printf("\n");
printf("----------------------------------------------------------------------------\n");
printf("\n");
return -;
}
} /*
* 主函数
*/
int main()
{
int Case=,in;
while(){
in = Menu(Case);
switch(in){
case -: //输入错误,进入下次循环
break;
case : //退出程序
printf("谢谢使用 :)\n");
return ;
case : //加密
Encryption();
break;
case : //解密
Decryption();
break;
}
}
return ;
}

Freecode : www.cnblogs.com/yym2013

DES加密算法实现的更多相关文章

  1. 在.NET Core 里使用 BouncyCastle 的DES加密算法

    .NET Core上面的DES等加密算法要等到1.2 才支持,我们可是急需这个算法的支持,文章<使用 JavaScriptService 在.NET Core 里实现DES加密算法>需要用 ...

  2. 浅谈DES加密算法

    一.DES加密算法介绍 1.要求密钥必须是8个字节,即64bit长度 2.因为密钥是byte[8] , 代表字符串也可以是非可见的字节,可以与Base64编码算法一起使用 3.加密.解密都需要通过字节 ...

  3. JAVA使用DES加密算法加密解密

    程序中使用了.properties文件作为参数配置文档,好处是灵活配置各项参数 一旦对数据库的一些参数进行了配置,势必涉及数据库的IP,端口,用户名和密码 properties文件全是unicode编 ...

  4. 对称密码——DES加密算法

    前言 本篇博文将介绍对称密码算法中的DES密码的算法原理与代码实现(Java) DES算法原理 DES加密算法是对称加密算法(加密和解密使用同一个密钥)中的一种,DES也是分组密码,以64位为分组对明 ...

  5. des加密算法java&c#

    项目中用到的数据加密方式是ECB模式的DES加密得到的十六进制字符串.技术支持让写一个.net版的加密算法.这里做一下记录. java版: 16进制使用的是bouncycastle. import c ...

  6. android和.net webservice中的DES加密算法

    也是看了一堆的例子,本身并不会写加密算法,好在只要会用就行了,我们把在app中使用的参数加密,然后在.net端的webservice中进行解密,本身并没有什么问题,但是android下和.net下的d ...

  7. DES加密算法的C++实现

    <信息安全技术>这门课又在讲 DES 加密算法了,以前用纯C写过一次,这次我用 C++ 重新写了一个,写篇文章以备后用.本文介绍了 DES 算法加密的大致步骤和整体流程. 一.DES算法原 ...

  8. .net中DES加密算法研究

    /// <summary> /// DES加密算法 /// </summary> /// <param name="toEncrypt">要加密 ...

  9. 使用 JavaScriptService 在.NET Core 里实现DES加密算法

    文章<ASP.NET Core love JavaScript>和<跨平台的 NodeJS 组件解决 .NetCore 不支持 System.Drawing图形功能的若干问题> ...

  10. DES加密算法

    DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1976年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),随后在国际上广泛流传开 ...

随机推荐

  1. uniq命令注意事项,检查重复行的时候,只会检查相邻的行。

    今天在使用uniq命令统计数量时,uniq -c总是得不到想要的效果,相同的行没有合并,例如 后来在http://ju.outofmemory.cn/entry/78365才看到,原来uniq检查重复 ...

  2. jquery数组内多维对象

    jquery数组内多维对象 var postData=[],obj,list; obj = !!obj ? obj : $('#dist_meici_checkinfo_form'); obj.fin ...

  3. ubuntu14.04 archive sources.list

    deb http://archive.ubuntu.com/ubuntu/ trusty main restricted universe multiverse deb http://archive. ...

  4. 第三方登录(QQ登录)开发流程详解

    原文:http://www.cnblogs.com/it-cen/p/4338202.html 近排由于工作的繁忙,已经一个星期没写博文做分享了,接下来我对网站接入第三方登录----QQ登录的实现逻辑 ...

  5. Rubix - ReactJS Powered Admin Template 后台管理框架

    Rubix - ReactJS Powered Admin Template  后台管理框架,使用 ReactJS. http://rubix400.sketchpixy.com/ltr/charts ...

  6. mongoengine

    http://docs.mongodb.org/ecosystem/drivers/python/ http://www.cnblogs.com/holbrook/archive/2012/03/11 ...

  7. linux shell脚本通过参数名传递参数值

    平常在写shell脚本都是用$1,$2....这种方式来接收参数,然而这种接收参数的方式不但容易忘记且不易于理解和维护.Linux常用的命令都可指定参数名和参数值,然而我们怎样才能给自己的shell脚 ...

  8. nyoj_31

    题目描述:五个数求最值. #include <iostream> #include <algorithm> using namespace std; int main(){ ] ...

  9. .NET微信公众号开发-2.0创建自定义菜单

    一.前言 开发之前,我们需要阅读官方的接口说明文档,不得不吐槽一下,微信的这个官方文档真的很烂,但是,为了开发我们需要的功能,我们也不得不去看这些文档. 接口文档地址:http://mp.weixin ...

  10. C#复制、粘贴文本信息到剪贴板

    复制:private void button1_Click(object sender, System.EventArgs e) { // Takes the selected text from a ...