私は安全ではない小さなものを書こうとしています。目的はサーバ側のmp3を暗号化して、wgetや「別名で保存」してダウンロードすることはできず、平均的なJoeによって使用されるようにすることです。AES-CFBからJS forgeにアクセス
アイデアはレスポンスボディで暗号化されたmp3を送って、ヘッダにキーを送る、それを暗号化AES-CFB、mp3をロードし、サーバ側です。
サーバー側では、GoのstdlibとAES-CFB暗号化を使用しています。最初にbase64エンコーディングを使用した場合、暗号化された[] byte-sの単純な出力が得られます。
クライアント側私は偽造を使用して復号化しています。 xhrを送信し、arraybufferを読み込み、偽造を使って解読し、出力をコンソールに書き出します。
test.txtの内容は「これは単なるテストであり、おそらく動作していない可能性があります」となっています。
main.go
package main
import (
"net/http"
"io"
"crypto/rand"
"os"
"crypto/aes"
"crypto/cipher"
"fmt"
)
var (
key = "123456789"
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>
reader.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('123456789'));
decipher.start({iv: forge.util.createBuffer('123456789')});
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
出力は切り捨てられますが、それは同じだと、test.txtのです。あなたが見ることができるように、常にランダムなゴミを接頭辞としています。
私は間違っていますか? AES-CFBの偽造の実装が間違っているか、Go?彼らはなぜ互換性がないのですか?それとも、復号化が異なるのはなぜですか? AES-CFBが標準である場合、なぜ異なる実装が存在するのでしょうか?
また、gopherjsを代替として試してみましたが、a)コードサイズが大きすぎて(〜3.7MB)、b)gopherjsを使用して復号化されたオーディオを再生する方法がわかりません。しかしそれはちょうど脇にあるものです。
接頭辞を削除しました。接頭辞は16バイトになりました。音声を再生することは別の話です。あなたは正しく、16進数の出力は常に16バイトの接頭辞であることを示しています。 –