javascript - 从 Go 到 JS forge 的 AES-CFB

标签 javascript encryption go

我正在尝试写一些不安全的东西。目的是加密服务器端的 mp3,这样它们就不能用 wget 下载或“另存为”并被普通人使用。

思路在服务端,加载mp3,aes-cfb加密,在header中发送key,在response body中发送加密后的mp3。

服务器端使用 Go 的标准库和 AES-CFB 加密。首先使用 base64 编码,然后只是加密 []byte-s 的普通输出。

客户端我正在使用 forge 解密。我发送一个 xhr,读取数组缓冲区,使用 forge 解密并将输出写入控制台。

test.txt 的内容是“这只是一个测试,可能有效也可能无效。”

主.go

package main

import (
    "net/http"
    "io"
    "crypto/rand"
    "os"
    "crypto/aes"
    "crypto/cipher"
    "fmt"
)

var (
    key = "1234567890123456"
    fn = "test.txt"
)

func main() {

    http.Handle("/file/", http.HandlerFunc(serveFile))
    http.Handle("/", http.FileServer(http.Dir("public")))
    http.ListenAndServe(":8080", nil)
}

func serveFile(w http.ResponseWriter, r *http.Request) {
    file, e := os.Open(fn)
    if e != nil {
        fmt.Println(e.Error())
        return
    }
    defer file.Close()
    fi, _ := file.Stat()
    b := make([]byte, fi.Size())
    io.ReadFull(file, b)
    o := AESencrypt([]byte(key), b)
    w.Header().Set("Access-Control-Allow-Origin", "*")
    //w.Header().Set("Key", key)
    fmt.Println(o)
    fmt.Println(len(o))
    w.Write(o)
}

func AESencrypt(key []byte, content []byte) []byte {
    block, err := aes.NewCipher(key)
    if err != nil {
        panic(err)
    }
    ciphertext := make([]byte, aes.BlockSize + len(content))
    iv := ciphertext[:aes.BlockSize]
    if _, err := io.ReadFull(rand.Reader, iv); err != nil {
        panic(err)
    }
    stream := cipher.NewCFBEncrypter(block, iv)
    stream.XORKeyStream(ciphertext[aes.BlockSize:], content)
    return ciphertext
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>MP3 Player Demo</title>
</head>
<body>
<button onclick="loadFile('1')">Load</button>

<script src="node_modules/node-forge/js/forge.bundle.js"></script>
<script src="assets/reader.js"></script>
</body>
</html>

阅读器.js

function loadFile(filename) {
    //var context = new AudioContext || new webkitAudioContext();
    var request = new XMLHttpRequest();
    var url = "http://localhost:8080/file/";
    request.open("GET", url + filename, true);
    request.responseType = "arraybuffer";
    request.onload = function () {
        var rt = request.response;
        console.log(rt);
        var decipher = forge.cipher.createDecipher('AES-CFB', forge.util.createBuffer('1234567890123456'));
        decipher.start({iv: forge.util.createBuffer('1234567890123456')});
        decipher.update(forge.util.createBuffer(rt));
        decipher.finish();
        console.log(decipher.output);
        console.log(decipher.output.bytes());
        console.log('--------------');
    };

    request.send();
}

结果很奇怪。

它被“正确”解密,但是每个解密结果都有一个随机长度的前缀或垃圾。

3 个输出:

ArrayBuffer { byteLength: 69 }  reader.js:10:9
Object { data: "3~æÿK¥=®ªÿÂßthis is just a test…", read: 0, _constructedStringLength: 69 }  reader.js:16:9
3~æÿK¥=®ªÿÂßthis is just a test and maybe it's working maybe not.  reader.js:17:9
--------------  reader.js:18:9
ArrayBuffer { byteLength: 69 }  reader.js:10:9
Object { data: "ÅJÇ9Ë54«ÚV«this is just a test…", read: 0, _constructedStringLength: 69 }  reader.js:16:9
ÅJÇ9Ë54«ÚV«this is just a test and maybe it's working maybe not.  reader.js:17:9
--------------  reader.js:18:9
ArrayBuffer { byteLength: 69 }  reader.js:10:9
Object { data: "ªÕxïÂ`zqA   \cýx#this is just a test…", read: 0, _constructedStringLength: 69 }  reader.js:16:9
ªÕxïÂ`zqA   \cýx#this is just a test and maybe it's working maybe not.  reader.js:17:9
--------------  reader.js:18:9

这里的输出被 chop 了,但 test.txt 是一样的。如您所见,它总是以随机垃圾为前缀。

我做错了什么? AES-CFB 的伪造实现是错误的还是 Go 的?为什么他们不相容?或者为什么解密不同?如果 AES-CFB 是标准,为什么会有不同的实现?

我也尝试使用 gopherjs 作为替代方案,效果很好,但是 a) 代码太大 (~3.7MB) 并且 b) 我不知道如何使用 gopherjs 播放解密的音频。但这只是题外话。

最佳答案

您忘记移除 IV。这意味着 IV 也被“解密”,导致无意义。

废话好像解释成UTF-8,其中一个字符可能有多字节编码,所以你打印出来的IV的大小可能会有些不同。

因此删除 IV,并在调试二进制值时尝试打印出十六进制。

关于javascript - 从 Go 到 JS forge 的 AES-CFB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41521671/

相关文章:

java - BouncycaSTLe (SpongycaSTLe) key 导入和在android上的使用

C# 和 PHP 的 AES 加密结果不同

javascript - 使用 Javascript 按索引获取 HTML 有序列表中的元素

javascript - Bootstrap 输入字段上的 jQuery focus() 不起作用

javascript - 如何优化我的算法以使用子字符串进行搜索?

CGo 将 go 字符串转换为 *C.uchar

docker - CURL在Docker镜像中不起作用[无法访问Docker镜像中的主机]

javascript - 如何测试 React.js 组件外观?

java - 读取和插入 Chrome Cookies Java

go - 如何从 google-api-go-client 将日程设置到 Google 日历?