首页
关于
友情链接
推荐
百度一下
腾讯视频
百度一下
腾讯视频
Search
1
【笔记】用Javascript实现椭圆曲线加密算法
13 阅读
2
Hackergame 2022 个人题解
11 阅读
3
欢迎使用 Typecho
10 阅读
4
【博客折腾记录】l2d看板娘相关~
5 阅读
5
中国科学技术大学第六届信息安全大赛(HACKERGAME2019自我总结)
4 阅读
默认分类
登录
Search
标签搜索
Note
CPP
C
JavaScript
Math
CTF
Bilibili
Python
Docker
php
RSA
ECC
Crypto
Blog
Bash
FPGA
GAMES
Homework
依言 - Eyan
累计撰写
34
篇文章
累计收到
1
条评论
首页
栏目
默认分类
页面
关于
友情链接
推荐
百度一下
腾讯视频
百度一下
腾讯视频
搜索到
3
篇与
的结果
2019-12-06
【学习/笔记】RSA算法的c++实现
emmm先转载一篇文章吧RSA算法原理(一)非常推荐的一篇文章,我原本就想写个讲RSA算法的文章,然后发现这篇文章基本就可以满足我的要求了,所以就直接转过来了。这里主要讲c++代码。#include <bits/stdc++.h> #include <math.h> #include<ctime> using namespace std; #define randomInt(a,b) (rand()%(b-a+1)+a) typedef long long int ll; #define int ll struct rsakeys{ int p, q, n, fn, d, e; }; rsakeys* rsakey; ll mod_mul(ll a, ll b, ll mod){ ll res = 0; while (b){ if (b & 1) res = (res + a) % mod; a = (a + a) % mod; b >>= 1; } return res; } ll mod_pow(ll a, ll n, ll mod){ ll res = 1; while (n){ if (n & 1) res = mod_mul(res, a, mod); a = mod_mul(a, a, mod); n >>= 1; } return res; } // Miller-Rabin随机算法检测n是否为素数 bool Miller_Rabin(ll n){ if (n == 2) return true; if (n < 2 || !(n & 1)) return false; ll m = n - 1, k = 0; while (!(m & 1)) { k++; m >>= 1; } for (int i = 1; i <= 20; i++) // 20为Miller-Rabin测试的迭代次数 { ll a = rand() % (n - 1) + 1; ll x = mod_pow(a, m, n); ll y; for (int j = 1; j <= k; j++) { y = mod_mul(x, x, n); if (y == 1 && x != 1 && x != n - 1) return false; x = y; } if (y != 1) return false; } return true; } int gcd(int a,int b){ int r; while(b){ r=a%b; a=b; b=r; } return a; } int creat_prime(){ int tmp = 4; while(!Miller_Rabin(tmp))tmp=rand(); return tmp; } int create_keys(rsakeys* key){ srand((unsigned)time(NULL)); key->p = creat_prime(); cout<<"Your p is: "<<key->p<<endl; key->q = creat_prime(); cout<<"Your q is: "<<key->q<<endl; key->n=key->p*key->q; cout<<"Your n is: "<<key->n<<endl; key->fn = (key->p-1) * (key->q-1); cout<<"Your fn is: "<<key->fn<<endl; while(1){ key->e = rand()%key->fn; if(gcd(key->e,key->fn)==1)break; } cout<<"Your e is: "<<key->e<<endl; int k = 1; while((k*key->fn+1)%key->e){ k++; } key->d = (k*key->fn+1)/(key->e); cout<<"Your d is: "<<key->d<<endl; } int create_keys_by_pq(int p, int q, rsakeys* key){ cout<<p<<" "<<q<<endl; key->n = p * q; cout<<"Your n is: "<<key->n<<endl; key->fn = (p-1) * (q-1); cout<<"Your fn is: "<<key->fn<<endl; while(1){ key->e = rand()%key->fn; if(gcd(key->e,key->fn)==1)break; } cout<<"Your e is: "<<key->e<<endl; int k = 1; while((k*key->fn+1)%key->e){ k++; } key->d = (k*key->fn+1)/(key->e); cout<<"Your d is: "<<key->d<<endl; } int write_to_file(rsakeys* key){ ofstream d, e, n; d.open("d"); d<<key->d; e.open("e"); e<<key->e; n.open("n"); n<<key->n; d.close();e.close();n.close(); return 0; } int read_file(rsakeys* key){ ifstream d, e, n; d.open("d"); d>>key->d; e.open("e"); e>>key->e; n.open("n"); n>>key->n; d.close();e.close();n.close(); return 0; } signed main(){ rsakey = (rsakeys*)malloc(sizeof(rsakeys)); cout<<"============================================================"<<endl; cout<<"1. Creat keys and write to file."<<endl; cout<<"2. Creat keys by given p and q and write to file."<<endl; cout<<"3. Read keys from file."<<endl; cout<<"4. Encrypt a number."<<endl; cout<<"5. Decrypt a number."<<endl; cout<<"============================================================"<<endl; int d, e, n; while(1){ char command[64]; ll msg; ll key; ll inn; scanf("%s",command); if(!strcmp(command,"1")){ create_keys(rsakey); write_to_file(rsakey); } if(!strcmp(command,"2")){ int p,q; cin>>p>>q; create_keys_by_pq(p,q,rsakey); write_to_file(rsakey); } if(!strcmp(command,"3")){ read_file(rsakey); } if(!strcmp(command,"4")){ scanf("%d",&msg); cout<<mod_pow(msg,rsakey->e,rsakey->n)<<endl; } if(!strcmp(command,"5")){ scanf("%d",&msg); cout<<mod_pow(msg,rsakey->d,rsakey->n)<<endl; } } return 0; }就酱啦,再扔篇参考文章溜了。。。[[2]RSA密码的实现-你也能看的懂的python实现方法][2]
2019年12月06日
2 阅读
0 评论
0 点赞
2019-11-26
【笔记/学习】c++实现b站弹幕姬
差不多是为了后续某个功能插件的开发,于是开了这么个坑。之后还可以学习下相关知识,同时由于考试腾不出太多时间学习新知识所以拿旧项目顶一下,于是就有了这篇文章。。Step1.查找b站弹幕的http请求随便点开一个b站的直播间,打开f12,点击网络,刷新下,找有没有弹幕的相关请求包。之后可以发现“msg”这个包点开,从内容看,应该就是我们要找的弹幕包了(这里先略去具体的分析过程)然后就是http请求包的具体分析了。从浏览器中可以看到请求的网址,消息头和相关参数,下一步我们就要用c++去模拟请求了。step2.WinInet库的简单使用虽然用c++模拟请求时可以直接用底层的socket去发送请求,但为了方便,所以还是去直接使用相关库了。wininet库有点类似python的request库,这里就简单介绍使用wininet库去请求了。首先是使用wininet库必须包含的头文件:#include <Windows.h> #include <wininet.h> #pragma comment(lib,"wininet.lib")这里本来想贴一个之前学习时对我帮助挺大的一个网站的,结果找不到了,只能凭着自己的记忆写了。。首先,我们看一眼刚才的请求包,得知请求的网址是http://api.live.bilibili.com/ajax/msg,接下来我们用wininet的函数将网址分解。这里简单贴一段示例代码,看完应该就知道这个函数怎么用了:展开查看void CrackUrl() { URL_COMPONENTS uc; char Scheme[1000]; char HostName[1000]; char UserName[1000]; char Password[1000]; char UrlPath[1000]; char ExtraInfo[1000]; uc.dwStructSize = sizeof(uc); uc.lpszScheme = Scheme; uc.lpszHostName = HostName; uc.lpszUserName = UserName; uc.lpszPassword = Password; uc.lpszUrlPath = UrlPath; uc.lpszExtraInfo = ExtraInfo; uc.dwSchemeLength = 1000; uc.dwHostNameLength = 1000; uc.dwUserNameLength = 1000; uc.dwPasswordLength = 1000; uc.dwUrlPathLength = 1000; uc.dwExtraInfoLength = 1000; InternetCrackUrl("http://hoge:henyo@www.cool.ne.jp:8080/masapico/api_sample.index", 0, 0, &uc); printf("scheme: '%s'\n", uc.lpszScheme); printf("host name: '%s'\n", uc.lpszHostName); printf("port: %d\n", uc.nPort); printf("user name: '%s'\n", uc.lpszUserName); printf("password: '%s'\n", uc.lpszPassword); printf("url path: '%s'\n", uc.lpszUrlPath); printf("extra info: '%s'\n", uc.lpszExtraInfo); printf("scheme type: "); switch(uc.nScheme) { case INTERNET_SCHEME_PARTIAL: printf("partial.\n"); break; case INTERNET_SCHEME_UNKNOWN: printf("unknown.\n"); break; case INTERNET_SCHEME_DEFAULT: printf("default.\n"); break; case INTERNET_SCHEME_FTP: printf("FTP.\n"); break; case INTERNET_SCHEME_GOPHER: printf("GOPHER.\n"); break; case INTERNET_SCHEME_HTTP: printf("HTTP.\n"); break; case INTERNET_SCHEME_HTTPS: printf("HTTPS.\n"); break; case INTERNET_SCHEME_FILE: printf("FILE.\n"); break; case INTERNET_SCHEME_NEWS: printf("NEWS.\n"); break; case INTERNET_SCHEME_MAILTO: printf("MAILTO.\n"); break; default: printf("%d\n", uc.nScheme); } }然后是代码:#define URL_STRING L"http://api.live.bilibili.com/ajax/msg"//Bilive API TCHAR szHostName[128]; TCHAR szUrlPath[256]; URL_COMPONENTS crackedURL = { 0 }; crackedURL.dwStructSize = sizeof(URL_COMPONENTS); crackedURL.lpszHostName = szHostName; crackedURL.dwHostNameLength = ARRAYSIZE(szHostName); crackedURL.lpszUrlPath = szUrlPath; crackedURL.dwUrlPathLength = ARRAYSIZE(szUrlPath); InternetCrackUrl(URL_STRING, (DWORD)URL_STRING, 0, &crackedURL);之后是和服务器建立连接:HINTERNET hInternet = InternetOpen(L"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/15.0.849.0 Safari/535.1", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); if (hInternet == NULL) return -1; HINTERNET hHttpSession = InternetConnect(hInternet, crackedURL.lpszHostName, crackedURL.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); if (hHttpSession == NULL) { InternetCloseHandle(hInternet); std::cout << GetLastError(); return -2; } HINTERNET hHttpRequest = HttpOpenRequest(hHttpSession, L"POST", crackedURL.lpszUrlPath, NULL, L"", NULL, 0, 0); if (hHttpRequest == NULL) { InternetCloseHandle(hHttpSession); InternetCloseHandle(hInternet); return -3; }这三个函数从名字应该就能基本理解它们的作用了,我自己也不是特别精通就不讲了,感觉学过socket编程的话应该不难理解emm。。然后就是向服务器发送请求了。#define _HTTP_ARAC L"Content-Type: application/x-www-form-urlencoded\r\n" char _HTTP_POST[] = "roomid=5322&csrf_token=&csrf=&visit_id=";//roomid parameters. DWORD dwRetCode = 0; DWORD dwSizeOfRq = sizeof(DWORD); if (!HttpSendRequest(hHttpRequest, _HTTP_ARAC, 0, _HTTP_POST, sizeof(_HTTP_POST)) || !HttpQueryInfo(hHttpRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwRetCode, &dwSizeOfRq, NULL) || dwRetCode >= 400) { InternetCloseHandle(hHttpRequest); InternetCloseHandle(hHttpSession); InternetCloseHandle(hInternet); return -4; }经过实验,发现在基本的请求头的基础上必须要加上content-type,服务器才能正确的返回json数据,参数方面只需要roomid,其他参数都留空就可以正常使用。HttpSendRequest()就是发送http请求的函数了,应该不难看懂吧。最后就是接收服务器返回的数据了#define READ_BUFFER_SIZE 1024 std::string strRet = ""; BOOL bRet = FALSE; char szBuffer[READ_BUFFER_SIZE + 1] = { 0 }; DWORD dwReadSize = READ_BUFFER_SIZE; while (true){ bRet = InternetReadFile(hHttpRequest, szBuffer, READ_BUFFER_SIZE, &dwReadSize); if (!bRet || (0 == dwReadSize)){ break; } szBuffer[dwReadSize] = '\0'; strRet.append(szBuffer); }代码应该不难看懂吧,不过最初写这段代码的时候我被坑过。虽然InternetReadFile()可以指定自己要接收的字节数,但实际每次接收的数据不一定是你写的字节数,最后总会有几个字节是乱码。所以必须用到函数给出的接收到的字节数,在后面手动加一个'\0'才行。这样,我们就得到了想要的数据并储存到string里了。step3.项目的c++实现这里json数据的解析我用的是CJsonObject,用法参考我上篇转载的博文。这里有个需要注意的地方:我们每次的请求实际上返回的是最近的10条弹幕的数据,而我们要的是持续的弹幕姬,所以我的做法是循环进行请求,每次请求后与上次的请求进行比较,打印出不同的数据,来达到想要的效果。typedef struct { int uid; std::string name; std::string time; std::string text; } DM_DATA; DM_DATA old_list[10] = { 0 }; DM_DATA new_list[10] = { 0 };这里简单定义一个结构体,并认为:假如弹幕的发送者uid,发送时间,发送内容都相同的话,就认为这是同一条弹幕,就不打印。如果有人在一秒内发送多条相同的弹幕那我也没办法啦╮( ̄▽ ̄)╭不过这种情况并不常见而且也没多大影响。neb::CJsonObject oJson(strRet); for (int i = 0; i < 10; i++) { oJson["data"]["room"][i].Get("uid", new_list[i].uid); if (new_list[i].uid == 0)break; oJson["data"]["room"][i].Get("nickname", new_list[i].name); oJson["data"]["room"][i].Get("timeline", new_list[i].time); oJson["data"]["room"][i].Get("text", new_list[i].text); } for (int j = 0; j < 10; j++) { int k = 1; for (int i = 0; i < 10; i++) { if (old_list[i].uid == new_list[j].uid && old_list[i].name == new_list[j].name && old_list[i].time == new_list[j].time && old_list[i].text == new_list[j].text)k = 0; } if (k)std::cout << "[" << new_list[j].name << "]" << new_list[j].text << std::endl; } for (int i = 0; i < 10; i++) { old_list[i].uid = new_list[i].uid; old_list[i].name = new_list[i].name; old_list[i].time = new_list[i].time; old_list[i].text = new_list[i].text; } Sleep(3000);neb::CJsonObject oJson(strRet);这条语句用来处理刚刚接收的json数据,然后下面的三个循环应该很好理解,第一个循环用来把接收到的数据存入新数组,第二个循环进行新数组与旧数组的比较,如不相同则打印,第三个循环把新数组的内容存入旧数组中。最后的Sleep(3000);用来防止请求过快被服务器ban。最后我们需要的就是循环了,由于有点偷懒的原因,所以最后就加一句goto label;,把label:放在HttpSendRequest 的前面就可以了。这样程序的设计就基本完成了。不过还需要注意的一点是,服务器返回的数据是utf8编码的,而大多数中文的windows默认是GBK编码,所以直接转换数据会乱码。最开始的时候我从网上copy了个utf8转gbk的函数,不过现在有更简单的方法,直接在代码的最前面加上一句system("chcp 65001");把控制台的编码换成utf8就ok了。最后放个我在github上的这个项目的旧版本吧:https://github.com/panedioic/CPPDanmaku参考资料:[[1]【python】b站直播弹幕获取][2]by 猫先生的早茶[[3]WinInet编程详解]4获取bilibili直播弹幕的WebSocket协议][3]by 炒鸡嗨客协管徐by skilledprogrammer[[4]C++实现Http Post请求][5]by DoubleLi[[5]WinInet使用详解][6]by analogous_love
2019年11月26日
0 阅读
0 评论
0 点赞
2019-11-19
【转载】C/C++遍历目录下的所有文件(Windows/Linux篇,超详细)
本文可转载,转载请注明出处:http://www.cnblogs.com/collectionne/p/6815924.html。前面的一篇文章我们讲了用Windows API遍历一个目录下的所有文件,这次我们讲用一种Windows/Linux通用的方法遍历一个目录下的所有文件。Windows/Linux的IDE都会提供一个头文件——<io.h>。看名字,似乎是关于I/O的,但是实际上它还提供了类似于WIN32_FIND_DATA、FindFirstFile()、FindNextFile()和FindClose()的查找文件的功能。_finddata_t结构_finddata_t结构用来记录查找到的文件的信息。实际上有_finddata32_t、_finddata32i64_t、_finddata64i32_t、_finddata64_t、_wfinddata32_t、_wfinddata32i64_t、_wfinddata64i32_t、_wfinddata64_t八个结构,但都只是在32位/64位整数和字符类型上有所区别,但整体上相同。大致定义如下(MSDN):struct _finddata_t { unsigned attrib; size_t time_create; size_t time_access; size_t time_write; _fsize_t size; char name[_MAX_PATH]; };对于不同的_finddata_t结构,time_create、time_access和time_write的类型为_time32_t或_time64_t,size的类型为_fsize_t或__int64,name为char[_MAX_PATH]或wchar_t[_MAX_PATH]。attribunsigned类型,文件属性。time_create_time32_t/_time64_t类型,文件创建时间(FAT文件系统为-1)。以UTC格式存储,如果需要转换成当地时间,使用localtime_s()。time_access_time32_t/_time64_t类型,文件最后一次被访问的时间(FAT文件系统为-1)。以UTC格式存储,如果需要转换成当地时间,使用localtime_s()。time_write_time32_t/_time64_t类型,文件最后一次被写入的时间。以UTC格式存储,如果需要转换成当地时间,使用localtime_s()。size_fsize_t/__int64类型,文件的长度(以字节为单位)。namechar[_MAX_PATH]/wchar_t[_MAX_PATH]类型,文件/目录名,不包含路径。对于不支持文件创建时间、文件上一次访问时间的文件系统,time_create和time_access为-1。_MAX_PATH在stdlib.h中被定义为260。一般_finddata_t被定义为_finddata32_t/_finddata64i32_t,_wfinddata_t被定义为_wfinddata32_t/_wfinddata64i32_t。为方便,下文中将_finddata_t和_wfinddata_t统称为_finddata_t。文件属性常量一个文件/目录可以有多种属性,每种属性可以是下面列出的属性之一。_A_ARCH档案。文件被BACKUP指令改变或清除时被设置。值:0x20。_A_HIDDEN隐藏。使用DIR指令一般看不到,除非使用/AH选项。值:0x02。_A_NORMAL普通。文件没有更多属性被设置,可以没有限制地被读或写。值:0x00。_A_RDONLY只读。不能以“写”为目的打开该文件,并且不能创建同名的文件。值:0x01。_A_SUBDIR子目录。值:0x10。_A_SYSTEM系统文件。使用DIR指令一般看不见,除非使用/A或/A:S选项。值:0x04。要检查x是否含有某个属性a,可以用x & a进行检查。指定多个属性可以使用按位or运算符,例如_A_SYSTEM | _A_RDONLY | _A_HIDDEN。通配符(wildcards)遍历文件目录时需要使用通配符,详见我的另一篇文章。_findfirst()/_findnext()/_findclose()函数_findfirst()函数intptr_t _findfirst( const char * filespec, struct _finddata_t *fileinfo );实际上_findfirst()有10个版本,这里只列出一个。filespecconst char /const wchar_t 类型,目标文件说明(可包含通配符)。fileinfo_finddata_t *类型,函数将会填入文件/目录信息。返回值如果成功,返回一个唯一的搜索句柄标识一个或一组和filespec说明匹配的文件,可以用于接下来的_findnext()和_findclose()函数。否则_findfirst()返回-1。注意,intptr_t并不是指针类型,只是int或__int64的typedef。_findnext()函数int _findnext( intptr_t handle, struct _finddata_t *fileinfo );handleintptr_t类型,搜索句柄。fileinfo_finddata_t *类型,函数将会填入文件/目录信息。返回值如果成功,返回0,否则返回-1。如果没有更多能够找到的文件了,也会导致失败。_findclose()函数int _findclose( intptr_t handle );关闭搜索句柄并释放相应的资源。handle搜索句柄。返回值成功返回0,失败返回-1。程序代码[toc]1. 遍历目录下的所有文件#include <iostream> #include <cstring> // for strcat() #include <io.h> using namespace std; void listFiles(const char * dir); int main() { char dir[200]; cout << "Enter a directory (ends with \'\\\'): "; cin.getline(dir, 200); strcat(dir, "*.*"); // 在要遍历的目录后加上通配符 listFiles(dir); return 0; } void listFiles(const char * dir) { intptr_t handle; _finddata_t findData; handle = _findfirst(dir, &findData); // 查找目录中的第一个文件 if (handle == -1) { cout << "Failed to find first file!\n"; return; } do { if (findData.attrib & _A_SUBDIR && strcmp(findData.name, ".") == 0 && strcmp(findData.name, "..") == 0 ) // 是否是子目录并且不为"."或".." cout << findData.name << "\t<dir>\n"; else cout << findData.name << "\t" << findData.size << endl; } while (_findnext(handle, &findData) == 0); // 查找目录中的下一个文件 cout << "Done!\n"; _findclose(handle); // 关闭搜索句柄 }程序遍历目录下的所有文件/目录,如果是文件则输出文件大小。注意_findnext()函数成功返回0,因此要加上==0或!=-1进行判断,不能省略。此外还有一个值得注意的地方:if (findData.attrib & _A_SUBDIR || strcmp(findData.name, ".") || strcmp(findData.name, "..") )使用_findfirst()、_findnext()进行搜索时,可能会得到"."和".."两个文件夹名。这两个值可以忽略。[toc]2. 遍历目录中的所有文件注意是“目录中”而不是“目录下”,这个程序将会遍历一个目录里包含的所有文件。#include <iostream> #include <cstring> // for strcpy(), strcat() #include <io.h> using namespace std; void listFiles(const char * dir); int main() { char dir[200]; cout << "Enter a directory: "; cin.getline(dir, 200); listFiles(dir); return 0; } void listFiles(const char * dir) { char dirNew[200]; strcpy(dirNew, dir); strcat(dirNew, "\\*.*"); // 在目录后面加上"\\*.*"进行第一次搜索 intptr_t handle; _finddata_t findData; handle = _findfirst(dirNew, &findData); if (handle == -1) // 检查是否成功 return; do { if (findData.attrib & _A_SUBDIR) { if (strcmp(findData.name, ".") == 0 || strcmp(findData.name, "..") == 0) continue; cout << findData.name << "\t<dir>\n"; // 在目录后面加上"\\"和搜索到的目录名进行下一次搜索 strcpy(dirNew, dir); strcat(dirNew, "\\"); strcat(dirNew, findData.name); listFiles(dirNew); } else cout << findData.name << "\t" << findData.size << " bytes.\n"; } while (_findnext(handle, &findData) == 0); _findclose(handle); // 关闭搜索句柄 }
2019年11月19日
1 阅读
0 评论
0 点赞