【ctf-3】数论基础+Crypto初步

本周继续学习了公钥密码学的数论基础,最近事情实在太多了只能海绵里挤时间了。当然关于数论这个部分还是非常重要的,不仅实在密码学部分还在是在算法设计部分都至关重要的,本人也还没有深入接触过python,php,对于一些脚本处理大多还是用的C++,这一点日后需要提高,很多关于密码的解法大多是用python的。同时本周也进行了Cyrpto的题目练习,确实让我大开了眼界,认识了很多加密方式,对于此可以看总结部分! 总得来说,密码学需要观察同时给也需要积累,没有任何积累在做题的时候根本无从下手!同时不仅在做题也得要进行总结,对于密码加密方式必须要进行总结否则就是做了后面的忘了前面的!

前言:数论——这是同余理论的核心内容,而且也是公钥密码学最重要基础理论,同余方程求解方法在许多密码学算法的设计中有重要的应用,例如求解一次同余方程式许多密码学算法加、解密甚至破译的最基本的运算内容;孙子定理、二次剩余、Jacobi符号可以用于素检测与设计伪随机生成器。

数论基础

1.一元高次同余方程 f ( x ) = a n x n + . . . + a 1 x + a 0 f(x)=a_nx^{n}+...+a_1x+a_0 f(x)=anxn+...+a1x+a0则含有变量的同余式
f ( x ) ≡ 0 ( m o d m ) f(x)\equiv 0(mod m) f(x)0(modm)这个叫做模m的同余方程,若整数c满足 f ( c ) ≡ 0 ( m o d m ) f(c)\equiv 0(mod m) f(c)0(modm)则称c是同余方程的解。
2.性质1:若f(x)-g(x)=km,则f(x)-0=nm与g(x)-0=cm的解相同且解数相同,这个应该很容易就看出了。当然了也可以进行一个推论:f(x)=q(x)h(x)+r(x)与同余方程h(x)-0=km是恒等同余式,即方程的解数为m,则f(x)-0=km与r(x)-0=km是解与解数相同。
另外利用恒等同余式降低同余方程的次数,关键是找模m的恒等同余式,如果m为素数p,则:
h ( x ) = x p − x ≡ 0 ( m o d p ) h(x)=x^{p}-x\equiv 0(mod p) h(x)=xpx0(modp)

例如1求解 5 x 3 − 3 x 2 + 3 x − 1 ≡ 0 ( m o d 11 ) 5x^{3}-3x^{2}+3x-1\equiv 0 (mod 11) 5x33x2+3x10(mod11)
这种题怎么做呢?首先分析模11,他的绝对最小完全剩余系是-5,-4,…4,5,当x=2的时候是上述一个解,那么很明显答案就是x-2=11k了。

例如2求解 f ( x ) = 4 x 2 − 27 x − 9 ≡ 0 ( m o d 15 ) f(x)=4x^{2}-27x-9\equiv 0(mod 15) f(x)=4x227x90(mod15)
这个题目怎么分析呢,首先发现模15是有素因子3和5的,也就是说我们只用考虑f(1)-f(5)就可以了,但是上述式子均不等于故无解(区别上题目,其实也可以使用绝对最小完全剩余系来看)

3.一次同余方程 a x ≡ b ( m o d m ) ax\equiv b(mod m) axb(modm)
若(a,m)=1,则同余方程ax-b=km有且仅有一个解。
这个怎么证明呢?采用逆元的思想,同时使用Euler定理(这个定理不要忘了哈)
4.关于孙子定理、二次剩余在下次笔记中补充。

数论算法代码C++

1.阶乘最后非零位。
这是一个公式递归

Let D(n) be the last non-zero digit in n!
If tens digit (or second last digit) of n is odd
    D(n) = 4 * D(floor(n/5)) * D(Unit digit of n) 
If tens digit (or second last digit) of n is even
    D(n) = 6 * D(floor(n/5)) * D(Unit digit of n)

下面附代码:

#include <iostream>
#include <cmath>
#include <cstdlib>
using namespace std;

int dig[] = {1, 1, 2, 6, 4, 2, 2, 4, 2, 8};

int last(int n){
    if(n<=9) return dig[n];
    else{
        if((n/10)%10==2){
            //D(n)=4*D(floor(n/5))*D(unit dit of n)
            return (6*last(n/5)*dig[n%10])%10;
        }else{
            return (4*last(n/5)*dig[n%10])%10;
        }
    }
}

int main(){
    int n;cin>>n;
    cout<<last(n)<<endl;
    return 0;
}

2.扩展Euclid求解gcd(a,b)=ax+by

int ext_gcd(int a,int b,int& x,int& y){
	int t,ret;
	if (!b){
		x=1,y=0;
		return a;
	}
	ret=ext_gcd(b,a%b,x,y);
	t=x,x=y,y=t-a/b*y;
	return ret;
}

3.求解模线性方程组(中国余数定理)

//  x = b[0] (mod w[0])
//  x = b[1] (mod w[1])
//  ...
//  x = b[k-1] (mod w[k-1])
//要求w[i]>0,w[i]与w[j]互质,解的范围1..n,n=w[0]*w[1]*...*w[k-1]
int modular_linear_system(int b[],int w[],int k){
	int d,x,y,a=0,m,n=1,i;
	for (i=0;i<k;i++)
		n*=w[i];
	for (i=0;i<k;i++){
		m=n/w[i];
		d=ext_gcd(w[i],m,x,y);
		a=(a+y*m*b[i])%n;
	}
	return (a+n)%n;
}

4.素数随机判定

int modular_exponent(int a,int b,int n){ //a^b mod n
	int ret;
	for (;b;b>>=1,a=(int)((i64)a)*a%n)
		if (b&1)
			ret=(int)((i64)ret)*a%n;
	return ret;
}

// Carmicheal number: 561,41041,825265,321197185
int miller_rabin(int n,int time=10){
	if (n==1||(n!=2&&!(n%2))||(n!=3&&!(n%3))||(n!=5&&!(n%5))||(n!=7&&!(n%7)))
		return 0;
	while (time--)
		if (modular_exponent(((rand()&0x7fff<<16)+rand()&0x7fff+rand()&0x7fff)%(n-1)+1,n-1,n)!=1)
			return 0;
	return 1;
}

5.求1…n-1中与n互质的数的个数

int eular(int n){
	int ret=1,i;
	for (i=2;i*i<=n;i++)
		if (n%i==0){
			n/=i,ret*=i-1;
			while (n%i==0)
				n/=i,ret*=i;
		}
	if (n>1)
		ret*=n-1;
	return ret;
}

6.求解模线性方程ax=b (mod n)

int modular_linear(int a,int b,int n,int* sol){
	int d,e,x,y,i;
	d=ext_gcd(a,n,x,y);
	if (b%d)
		return 0;
	e=(x*(b/d)%n+n)%n;
	for (i=0;i<d;i++)
		sol[i]=(e+i*(n/d))%n;
	return d;
}

CTF-Crypto wp

1.老师让小明抄写一段话,结果粗心的小明把部分数字抄成了字母,还因为强迫症把所有字母都换成大写。你能帮小明恢复并解开答案吗:QWIHBLGZZXJSXZNVBZW

拿到这个题目表示很迷,因为根本不知道怎么入手,但是从部分数字抄成字母了,这一点就比较好突破,当时可以用脚本跑出来,而本人还没有进入python脚本学习模块,所以只能用暴力法来凑。
首先我把感觉像数字的字母都标志了出来,基本上就是这些情况了。

I->1 B->8 Z->2 S->5 q->9 i->1 b->6 l->1 z->2 s->5

列举出一些情况,在base64平台进行解码:
在这里插入图片描述
看了大神的代码部分,可以在php在线运行,直接使用base64进行解码,也就是说需要知道这是base64加密的,一般来说可以通过英文+数字的方法来试一下**,原文有数字有字母所以考虑base64,4个为一组是因为base64把明文的3字节加密为4字节**

<?php
$list=array();
function fun($str,$index=0){

    if($index==strlen($str)){
        global $list;
        $ret=base64_decode($str);
        $list[]=$ret;
        return false;
    }
    $head=substr($str,0,$index);
    $mid=substr($str,$index,1);
    $end=substr($str,$index+1,strlen($str)-$index);
    $words=getWord($mid);
    foreach ($words as $key=>$v){
        $newStr=$head.$v;
        $ret=base64_decode($newStr);
        if(!preg_match('/[^a-zA-Z\d\_\-]/is',$ret)){
            fun($newStr.$end,$index+1);
        }
    }
}
function getWord($c){
    $word=array("I"=>1, 'L'=>1, 'G'=>9, 'Z'=>2, 'S'=>5);
    $arr=array($c,strtolower($c));
    if(isset($word[$c])){
        $arr[]=$word[$c];
    }
    return $arr;
}
$str="QWIHBLGZZXJSXZNVBZW";
fun($str);
//var_dump($list);
foreach($list as $result){
    if(strpos($result,'Aman')===0){
	echo $result;
	echo "\n";
    }
}
?>

2题目:…-./.-…/.-/–./----.–/-…/…–/…-./-.-./-…/…-./.----/–…/…-./----./…–/----./----./…/-----/…-/-----.-,解密

很简单的一道题目,这是非常明显的摩斯密码,故只要在平台运行即可,得到的如下图:
在这里插入图片描述
FLAG{D3FCBF17F9399504} 然后明文其实是小写的,这个摩斯密码对英文字符是没有大小写之分的
flag{d3fcbf17f9399504}

3.一只小羊翻过了2个栅栏 fa{fe13f590lg6d46d0d0}

这个也是比较明显的解密,栅栏—联想到栅栏密码,故在线运行即可得出。
flag{6fde4163df05d900}

  1. +++++ +++++ [->++ +++++ +++<] >++.+ +++++ .<+++ [->-- -<]>- -.+++ +++.< ++++[ ->+++ +<]>+ +++.< +++++ +++[- >---- ----< ]>— ----- —.< +++++ ++[-> +++++ ++<]> +++.< +++++ +[->- ----- <]>-- ----- -.–. ----. --.++ +++++ +.<++ ++++[ ->+++ +++<] >++++ +.++. <++++ ++[-> ----- -<]>- ----- ----. -.<++ +++++ [->++ +++++ <]>+. ----. ++++. <++++ +++[- >---- —<] >---- .+.<+ +++++ ++[-> +++++ +++<] >++++ +++++ ++.<

这个不清楚具体的做法,只能参考大神的wp并以此拓宽眼界了。
这个网址Brainfuck to Text
在这里插入图片描述

5.你喜欢下棋吗?你喜欢下棋吗?
解压密码为小写
4423244324433534315412244543

你喜欢下棋吗?应该能看得出是棋盘密码(Polybius)
在这里插入图片描述
解压压缩包
在这里插入图片描述

在线解码
棋盘码解密压缩包得到密文,密文通过博多码解密得到明文,解出的明文要小写,此外解出的O是数字0。
在这里插入图片描述

6.md5的构成:bci177a7a9c7udf69c248647b4dfc6fd84o

了解MD5构造,删除不需要的,然后解密即可
flag{666666666666}

7.easy_crypto:0010 0100 01 110 1111011 11 11111 010 000 0 001101 1010 111 100 0 001101 01111 000 001101 00 10 1 0 010 0 000 1 01111 10 11110 101011 1111101

拿到题目和之前摩斯密码一样的道理,写一个函数让0变为. 1-> - 空格为/

#include <iostream>
#include <string>
#include <cstring>
using namespace std;

string s="0010 0100 01 110 1111011 11 11111 010 000 0 001101 1010 111 100 0 001101 01111 000 001101 00 10 1 0 010 0 000 1 01111 10 11110 101011 1111101";

int main(){
    string m="";
    for(int i=0;i<s.length();i++){
        if(s[i]=='0') m+=".";
        else if(s[i]=='1') m+="-";
        else m+="/";
    }
    cout<<m<<endl;
    return 0;
}
//..-./.-../.-/--./----.--/--/-----/.-./..././..--.-/-.-./---/-.././..--.-/.----/.../..--.-/../-./-/./.-././.../-/.----/-./----./-.-.--/-----.-

放在摩斯解码上去
在这里插入图片描述
flag{m0rse_code_1s_interest1n9!} (最后讲摩斯密码构成)
1、莫尔斯 2、%u7b={} 3、描述:01

总结

这几天做了蛮多道关于Cyrpto的题目,总的来说还是比较有感悟的,首先是面对很多题目根本没有一丝头绪,简直就是在瞎子摸黑,但是经过了上述题目的训练也得到了很多,例如摩斯密码棋盘密码啊,等等。但是如果你该如何区总结这些密码要旨呢?我想只有不断地去总结才会有收获,此刻我将列举出以上的一些密码解法,关键是想到为什么是这个。这里给出一般在ctf常见的密码学部分,点击此处

base64

首先对于第一个题目我根本不清楚是用base64,但是我知道有很多种情况,然而为什么是base64这就是比较深思的问题了。
Base64是一种将二进制流表示为 64 个字符的编码方式。当然出现了英文和数字要有Base64解密的想法
在这里插入图片描述
分组转换过程:从二进制流头部开始,每 6 位为一组,若不足 6 位,则低位补0
每 6 位组成一个新的字节,高位 2 位补 0 ,此时已经获得二进制的Base64编码
步骤3:转换为字符串 将二进制的Base64编码每个字节映射为一个字符,例如0000 0000映射为 A,0011 1111映射为/,此时已经获得Base64编码字符串
步骤4:末尾补位 标准Base64编码字符串的长度为 4 的倍数,否则,在末尾补充=(这个很关键,第一题就必须要进行添加=)。例如前面的QmFzZTY0IOe8lueggQ==长度就是补充了两个=后,长度为 20。
在这里插入图片描述
以谷歌网站为例:
在这里插入图片描述
在这里插入图片描述
需要注意的是,Base64并不是一种加密方式,明文使用Base64编码后的字符串通过索引表可以直接还原为明文。因此,Base64只能作为一种数据的存储格式。
算法

import java.util.Base64;

标准 Base 64
System.out.println(Base64.getEncoder().encodeToString("".getBytes()));

Url Base 64
System.out.println(Base64.getUrlEncoder().encodeToString("".getBytes()));

MIME Base 64
System.out.println(Base64.getMimeEncoder().encodeToString("".getBytes()));

摩斯密码

点(·):1
划(-):111
字符内部的停顿(在点和划之间):0
字符之间的停顿:000
单词之间的停顿:0000000
注意有些网站解密以后会出现许多莫名其妙的空格还有转义字符%u33。
这里就推荐这个解密网站,不过注意的是明文都是小写的。

栅栏密码

这个在上述题目给的提示是过了栅栏,如果不知道的话就真的不知道了。
栅栏密码可以分为两类,第一种是N型栅栏密码、第二种是V型栅栏密码,如果是遇到数字部分可以选择猜一下。

博多码

题目是一种5bit的编码,联想:博多码是由5个长度相同的“通”、“断”信号组成的电码(感觉和摩斯密码有点相同的,以后要是0.1可以尝试一下),按不同方式组合而成的电码组共有32种,每种表示一个书写符号,它比利用由长划和短点组成的莫尔斯电码的通信效率高。现代的博多电码,通常用7或8个“通”、“断”信号组成。

Brainfuck

这个题目其实比较明显了,记住brainfuck的密码形式.
在这里插入图片描述
第一次遇到这么奇怪的编程语言,怪不得是叫f**k.
在这里插入图片描述

棋盘密码

棋盘密码是指密码破解规则中的字母或数字如棋盘一样排列的一种暗号密码。最早的,也是最经典的棋盘密码为波利比奥斯棋盘(PolybiusCheckerboard)。它是以波利比奥斯矩阵为排列顺序的一种数字与字母的密码表,当然每个国家的密码排布并不一样,这里只展示最常用的一种排布方式。
判断是否是用棋盘密码破解的方式页很简单,只要出现数字是成双出现的数组串,而且有出现最大数字大于26的,那是棋盘密码的可能性就很大。

MD5

MD5构造,删除不需要的,然后解密即可,**范围是32个,分别是0-9,a-f,**这一点需要注意,一般题目中也会给一些提示的。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值