【计算机科学导论实验】信息隐藏 题解

前言

本文提供计算机科学导论课程“信息隐藏”实验的个人思路,仅供参考。
原题链接请戳这里

为避免抄袭,本文仅提供部分核心代码片段。

预备知识

strconv 是 Go 语言标准库中的一个包,用于字符串与基本数据类型之间的相互转换。本文给出的代码示例将使用 strconv 包中的如下函数:

func ParseInt(s string, base int, bitSize int) (i int64, err error)
func FormatInt(i int64, base int) string

其中, P a r s e I n t ParseInt ParseInt 用于将字符串 s s s b a s e base base 进制转为整数,并且该整数的位数不超过 b i t S i z e bitSize bitSize b i t S i z e = 0 , 8 , 16 , 32 , 64 bitSize=0,8,16,32,64 bitSize=0,8,16,32,64 分别代表 i n t , i n t 8 , i n t 16 , i n t 32 , i n t 64 int,int8,int16,int32,int64 int,int8,int16,int32,int64),若超出则会返回溢出错误,同时返回 b i t S i z e bitSize bitSize 能够表示的最大或最小值。

F o r m a t I n t FormatInt FormatInt 用于将整数 i i i 转为 b a s e base base 进制的字符串,返回类型为 s t r i n g string string

(关于 strconv 包的更详细知识,请参见这里

题解

本题思维难度几乎为零,我们需要处理的仅仅是 Golang 中令人生理不适的各种麻烦的类型转换。

隐藏程序

注意进行位运算前的强制转换即可。

func modify(value int,pix []byte,size int){
	for i:=0;i<size;i++{
		pix[i]=(pix[i] & 0xFC) | (byte(value) & 0x3)  //value类型为int,需要强制转换
		value>>=2
	}
}

恢复程序

重点在于 d e c o d e decode decode 函数的编写以及主程序中对图像文件的逐字节提取操作。

关于 d e c o d e decode decode 函数,我们需要对传入的 p i x pix pix 切片依次提取出每个元素字节的末两位,将其拼接后返回。为了方便,这里使用了 s t r c o n v . F o r m a t I n t strconv.FormatInt strconv.FormatInt 函数直接将提取后的字节元素以二进制的形式转换为字符串,最后拼接。

值得注意的是传入参数的类型必须为 i n t 64 int64 int64,所以要求强制转换。

func decode(pix[]byte) string{  //解码函数,对传入的pix切片依次提取出每个字节的末两位,返回类型为string
	s:=""
	for i:=0; i<len(pix); i++{
		temp:=strconv.FormatInt(int64(pix[i] & 0x3 | 0xF0),2)  //感谢知乎作者“资深韭菜”对strconv包函数的详解(原网址https://zhuanlan.zhihu.com/p/652026180)
		s=temp[len(temp)-2:]+s
	}
	return s
}

在主程序中,我们先对原文件的长度进行提取,然后依次逐字节提取原文件的每个字符。

	p,_:=os.ReadFile(image)
	size,_:=strconv.ParseInt(decode(p[S:S+T]),2,0)  //二进制字符串转整数,返回值为int64类型
	s:=[]byte{}
	for i:=0; i<int(size); i++{
		temp,_:=strconv.ParseInt(decode(p[S+T+i*C:S+T+(i+1)*C]),2,0)  //提取每个字节的字符,temp为int64类型
		s=append(s,byte(temp))  //强制转换,将temp加入最终输出的byte切片数组
	}
	os.WriteFile(txt,s,0644)

一些碎碎念

Go 语言对于不同类型参数之间的运算施加了诸多限制,而本题的代码实现由于牵扯到较多参数类型迥异的函数,故使用了极多的强制转换,这点对于初学 Go 语言的新手并不友好。

更多的雷点在于文本文件字符的处理上。由于可能涉及中文字符等 ASCII码大于 127 的非传统 ASCII 字符,输出结果时不能逐字节将 t e m p temp temp 转为字符( r u n e ( t e m p ) rune(temp) rune(temp))并拼接成字符串,会导致乱码出现。正确的做法在于直接将 b y t e ( t e m p ) byte(temp) byte(temp) 添加至 b y t e byte byte 切片类型数组的末尾。我不会告诉你这个bug我调了两小时TAT

就写到这吧,祝我 C a l c u l u s Calculus Calculus D M c o u r s e DMcourse DMcourse 期中考试顺利~

  • 15
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值