Go语言系统编程

首先

我正在学习可以理解Go系统编程的课程,并定期进行学习。

本次使用PNG图像的tEXt块来添加秘密文本。

※ 这篇由我撰写的Qiita文章是对这篇文章(https://ascii.jp/elem/000/001/260/1260449/)进行补充说明并整理成易于验证的形式。作为希望更深入了解的建议,我建议您阅读Qiita并理解其概念后再仔细阅读原始链接。

共享要做的事情想法 zuò de

PNG图像是由这样的块构成的。
※ CRC是类似于单元测试的块。

スクリーンショット 2021-04-12 12.27.42.png

通过使用tEXt块将秘密文本添加到PNG图像中,可以按照以下图像示例进行添加。

スクリーンショット 2021-04-12 12.30.27.png

显示PNG文件的块处理

以下是显示PNG文件块的处理方法。在这里准备一张PNG图像(在本文中为Fuga.png),然后执行这个处理过程。


package main

import (
    "encoding/binary"
    "fmt"
    "io"
    "os"
    "bytes"
)

func dumpChunk(chunk io.Reader) {
    var length int32
    binary.Read(chunk, binary.BigEndian, &length)
    buffer := make([]byte, 4)
    chunk.Read(buffer)
    fmt.Printf("chunk '%v' (%d bytes)\n", string(buffer), length)
}

func readChunks(file *os.File) []io.Reader {
    // チャンクを格納する配列
    var chunks []io.Reader

    // 最初の8バイトを飛ばす
    file.Seek(8, 0)
    var offset int64 = 8

    for {
        var length int32
        err := binary.Read(file, binary.BigEndian, &length)
        if err == io.EOF {
            break
        }
        chunks = append(chunks, io.NewSectionReader(file, offset, int64(length)+12))
        // 次のチャンクの先頭に移動
        // 現在位置は長さを読み終わった箇所なので
        // チャンク名(4バイト) + データ長 + CRC(4バイト)先に移動
        offset, _ = file.Seek(int64(length+8), 1)
    }
    return chunks
}

func main() {
    file, err := os.Open("Fuga.png")
    if err != nil {
        panic(err)
    }
    chunks := readChunks(file)
    for _, chunk := range chunks {
        dumpChunk(chunk)
    }
}

结果

$ go run displayChunk.go
chunk 'IHDR' (13 bytes)
chunk 'tIME' (7 bytes)
chunk 'pHYs' (9 bytes)
chunk 'gAMA' (4 bytes)
chunk 'IDAT' (63773 bytes)
chunk 'IEND' (0 bytes)

将PNG图像分解成块,以添加秘密文本为处理。


package main

import (
    "encoding/binary"
    "fmt"
    "io"
    "os"
    "hash/crc32"
    "bytes"
)

func textChunk(text string) io.Reader {
    byteData := []byte(text)
    var buffer bytes.Buffer
    binary.Write(&buffer, binary.BigEndian, int32(len(byteData)))
    buffer.WriteString("tEXt")
    buffer.Write(byteData)
    // CRCを計算して追加
    crc := crc32.NewIEEE()
    io.WriteString(crc, "tEXt")
    binary.Write(&buffer, binary.BigEndian, crc.Sum32())
    return &buffer
}

func dumpChunk(chunk io.Reader) {
    var length int32
    binary.Read(chunk, binary.BigEndian, &length)
    buffer := make([]byte, 4)
    chunk.Read(buffer)
    fmt.Printf("chunk '%v' (%d bytes)\n", string(buffer), length)
}

func readChunks(file *os.File) []io.Reader {
    // チャンクを格納する配列
    var chunks []io.Reader

    // 最初の8バイトを飛ばす
    file.Seek(8, 0)
    var offset int64 = 8

    for {
        var length int32
        err := binary.Read(file, binary.BigEndian, &length)
        if err == io.EOF {
            break
        }
        chunks = append(chunks, io.NewSectionReader(file, offset, int64(length)+12))
        // 次のチャンクの先頭に移動
        // 現在位置は長さを読み終わった箇所なので
        // チャンク名(4バイト) + データ長 + CRC(4バイト)先に移動
        offset, _ = file.Seek(int64(length+8), 1)
    }
    return chunks
}

func main() {
    file, err := os.Open("Fuga.png")
    if err != nil {
        panic(err)
    }
    defer file.Close()
    newFile, err := os.Create("FugaX.png")
    if err != nil {
        panic(err)
    }
    defer newFile.Close()
    chunks := readChunks(file)
    // シグニチャ書き込み
    io.WriteString(newFile, "\x89PNG\r\n\x1a\n")
    // 先頭に必要なIHDRチャンクを書き込み
    io.Copy(newFile, chunks[0])
    // テキストチャンクを追加
    io.Copy(newFile, textChunk("秘密のメッセージ"))
    // 残りのチャンクを追加
    for _, chunk := range chunks[1:] {
        io.Copy(newFile, chunk)
    }
}

执行addTextChunk.go后,会生成一个新的PNG图像(FugaX.png),其中插入了一段秘密的文本。

显示处理的是具有新的PNG图片块结构的添加了秘密文本的文件。

首先,我們將原先執行的displayChunk.go進行以下更改。

    • 指定PNG画像をFuga.pngからFugaX.pngに変更

 

    秘密のテキストを確認するための以下の処理をdumpChunk()に追加する。
if bytes.Equal(buffer, []byte("tEXt")) {
    rawText := make([]byte, length)
    chunk.Read(rawText)
    fmt.Println(string(rawText))
}

我们输入命令,尝试执行displayChunk.go!

$ go run displayChunk.go
chunk 'IHDR' (13 bytes)
chunk 'tEXt' (24 bytes)
秘密のメッセージ
chunk 'tIME' (7 bytes)
chunk 'pHYs' (9 bytes)
chunk 'gAMA' (4 bytes)
chunk 'IDAT' (63773 bytes)
chunk 'IEND' (0 bytes)

我成功查看了秘密信息!

请务必尝试在这样的感觉中插入秘密文章,试试看吧!

广告
将在 10 秒后关闭
bannerAds