base64编码与隐写

目标学了三天、说三遍
base64编码与隐写、base64编码与隐写、base64编码与隐写

* 代码实现 *


base64编码是网络上最常见的用于传输8Bit字节代码的编码方式之一。Base64编码可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。

1. base64编码规则:

  • 3个字符转换成4个字符
  • 每76个字符加一个换行符
  • 最后的结束符也要处理

2. base64编码码值:

A ~ Z、 a ~ z、0 ~ 9、+、/
一共64个字符,用这64个字符来加密文本字符。
64位只需要 (100000)b=64
6位二进制即可表示0~63这64个字符。
在这里插入图片描述

3.例子:对 (LOVE) 加密之后是 (TE9WRQ==)

可以看出A区补的是0,这里补1也可以,原因是因为不管补的是0还是1,都不会影响原文本E的值,那么这里就可以补 24 种情况。

在这里插入图片描述

这样,就知道了,后面需要补位的地方就可以用来隐写一些东西。
根据6、8倍数的关系,他们后面都可以通过补8、16位 01.对于补充的加密为‘=’。但是注意=不能用1来补位,因为这样就会改变原文本的值。

那么就可以知道

  1. 一个等号,就会有4位可以隐写的空间
  2. 两个等号,就会有2位可以隐写的空间

通过解释就可以用代码来练习练习。

当然这些都不需要你知道。因为PHP、py、Java……都封装好了,可以直接调用,这里不说,抵住诱惑。

但是为了加深理解,用c++来实现。

4. base64编码使用 :https://blog.csdn.net/qq_44009311/article/details/102755057#11

5. 代码如下:思路就是上面解释的二进制转换规律

下面写了解密的代码,加密都是类似的。

  1. base64解密 一个文件内的字符串

    #include<bits/stdc++.h>
    #define f(i,a,b) for(int (i)=(a);(i)<(b);(i)++)
    #define _f(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
    using namespace std;
    map<char,int> v;
    ifstream in("a.txt");//path路径
    string str="",str_01="",result="";
    int main() {
    	for(int i='A'; i<='Z'; i++) v[i]=i-'A';
    	for(int i='a'; i<='z'; i++) v[i]=i-'a'+26;
    	for(int i='0'; i<='9'; i++) v[i]=i-'0'+52;
    	v['+']=62,v['/']=63,v['=']=0;
    	printf("解密文本:\n");
    	while(str=str_01=result="",getline(in,str)) {
    		f(i,0,str.length()) _f(j,5,0) str_01+=('0'+((v[str[i]]>>j)&1));
    		for(int i=0,b=0; i<str_01.length(); result+=b,b=0,i+=8) _f(j,7,1) b|=((str_01[i+j]-'0')<<(7-j));
    		f(i,0,result.length()) printf("%c",result[i]);
    		puts("");
    	}
    	in.close();
    	return 0;
    }
    
  2. 在base64中找出 隐写的 flag

    #include <iostream>
    #include <map>
    #include <string>
    #include <fstream>
    #define f(i,a,b) for(int (i)=(a);(i)<(b);(i)++)
    #define _f(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
    using namespace std;
    int main() {
    	ifstream in("stego.txt");//把文本保存在a.txt
    	map<char,int> v; // 存储字符对应的base64编码
    	f(i,'A','Z'+1) v[i]=i-'A'+0;
    	f(i,'a','z'+1) v[i]=i-'a'+26;
    	f(i,'0','9'+1) v[i]=i-'0'+52;
    	v['+']=62,v['/']=63,v['=']=64;
    	string str="", str_01=""; //记录每行的字符串,每行文本对应的二进制
    	for(int d[4]; getline(in,str); ) {
    		_f(i,3,1) d[i]=v[str[str.length()-i]]; //取出每行的倒数三个
    		if(d[1] == 64) //从后面对第一个不为等号的字符进行提取,解码时1个字符对应6位二进制
    			if(d[2] == 64) _f(i,3,0) str_01+=('0'+((d[3]>>i)&1)); //末尾两个等号,说明倒数第三位字符有4位空间可以隐藏flag
    			else _f(i,1,0) str_01+=('0'+((d[2]>>i)&1)); //末尾有一个等号,说明倒数第二位字符有2位空间可以隐藏flag
    	}
    	printf("flag:\n");
    	for(int i=0,b=0; i<str_01.length(); printf("%c", b), b=0, i+=8) //把保存的二进制进行解析
    		_f(j,7,1) b|=((str_01[i+j]-'0')<<(7-j)); //8位二进制对应1位字符
    	printf("\n");
    	return 0;
    }
    

在这里插入图片描述






滴滴、、、滴滴答




猜你喜欢

转载自blog.csdn.net/qq_44009311/article/details/102770083