草庐IT

javascript - 从 Go 到 JS forge 的 AES-CFB

coder 2024-07-10 原文

我正在尝试写一些不安全的东西。目的是加密服务器端的 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/

有关javascript - 从 Go 到 JS forge 的 AES-CFB的更多相关文章

  1. ruby - Ruby 中的单 block AES 解密 - 2

    我需要尝试一些AES片段。我有一些密文c和一个keyk。密文已使用AES-CBC加密,并在前面加上IV。不存在填充,纯文本的长度是16的倍数。所以我这样做:aes=OpenSSL::Cipher::Cipher.new("AES-128-CCB")aes.decryptaes.key=kaes.iv=c[0..15]aes.update(c[16..63])+aes.final它工作得很好。现在我需要手动执行CBC模式,所以我需要单个block的“普通”AES解密。我正在尝试这个:aes=OpenSSL::Cipher::Cipher.new("AES-128-ECB")aes.dec

  2. ruby - 使用 AES 的 Rails 加密,过于复杂 - 2

    我在加密来self正在使用的第三方供应商的值时遇到问题。他们的指令如下:1)Converttheencryptionpasswordtoabytearray.2)Convertthevaluetobeencryptedtoabytearray.3)Theentirelengthofthearrayisinsertedasthefirstfourbytesontothefrontofthefirstblockoftheresultantbytearraybeforeencryption.4)EncryptthevalueusingAESwith:1.256-bitkeysize,2.25

  3. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  4. ruby - 在 Mechanize 中使用 JavaScript 单击链接 - 2

    我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan

  5. ruby-on-rails - Textmate 'Go to symbol' 相当于 Vim - 2

    在Railcasts上,我注意到一个非常有趣的功能“转到符号”窗口。它像Command-T一样工作,但显示当前文件中可用的类和方法。如何在vim中获取它? 最佳答案 尝试:helptags有各种程序和脚本可以生成标记文件。此外,标记文件格式非常简单,因此很容易将sed(1)或类似的脚本组合在一起,无论您使用何种语言,它们都可以生成标记文件。轻松获取标记文件(除了下载生成器之外)的关键在于格式化样式而不是实际解析语法。 关于ruby-on-rails-Textmate'Gotosymbol

  6. ruby - 如何在Elixir中使用AES CBC 128进行加密和解密 - 2

    我在Rails中有一个具有以下方法的应用程序,该方法可以加密和解密文本并与Java客户端通信。defencrypt(string,key)cipher=OpenSSL::Cipher::AES.new(128,:CBC)cipher.encryptcipher.padding=1cipher.key=hex_to_bin(Digest::SHA1.hexdigest(key)[0..32])cipher_text=cipher.update(string)cipher_textexcenddefhex_to_bin(str)[str].pack"H*"enddefbin_to_hex(

  7. javascript - jQuery 的 jquery-1.10.2.min.map 正在触发 404(未找到) - 2

    我看到有关未找到文件min.map的错误消息:GETjQuery'sjquery-1.10.2.min.mapistriggeringa404(NotFound)截图这是从哪里来的? 最佳答案 如果ChromeDevTools报告.map文件的404(可能是jquery-1.10.2.min.map、jquery.min.map或jquery-2.0.3.min.map,但任何事情都可能发生)首先要知道的是,这仅在使用DevTools时才会请求。您的用户不会遇到此404。现在您可以修复此问题或禁用sourcemap功能。修复:获取文

  8. ruby-on-rails - 我将 Rails3 与 tinymce 一起使用。如何呈现用户关闭浏览器javascript然后输入xss? - 2

    我有一个用Rails3编写的站点。我的帖子模型有一个名为“内容”的文本列。在帖子面板中,html表单使用tinymce将“content”列设置为textarea字段。在首页,因为使用了tinymce,post.html.erb的代码需要用这样的原始方法来实现。.好的,现在如果我关闭浏览器javascript,这个文本区域可以在没有tinymce的情况下输入,也许用户会输入任何xss,比如alert('xss');.我的前台会显示那个警告框。我尝试sanitize(@post.content)在posts_controller中,但sanitize方法将相互过滤tinymce样式。例如

  9. ruby - 使用 Selenium WebDriver 启用/禁用 javascript - 2

    出于某种原因,我必须为Firefox禁用javascript(手动,我们按照提到的步骤执行http://support.mozilla.org/en-US/kb/javascript-settings-for-interactive-web-pages#w_enabling-and-disabling-javascript)。使用Ruby的SeleniumWebDriver如何实现这一点? 最佳答案 是的,这是可能的。而是另一种方式。您首先需要查看链接Selenium::WebDriver::Firefox::Profile#[]=

  10. ruby - Watir-Webdriver 是否支持点击目标为 javascript 的链接? - 2

    我是Ruby和Watir-Webdriver的新手。我有一套用VBScript编写的站点自动化程序,我想将其转换为Ruby/Watir,因为我现在必须支持Firefox。我发现我真的很喜欢Ruby,而且我正在研究Watir,但我已经花了一周时间试图让Webdriver显示我的登录屏幕。该站点以带有“我同意”区域的“警告屏幕”开头。用户点击我同意并显示登录屏幕。我需要单击该区域以显示登录屏幕(这是同一页面,实际上是一个表单,只是隐藏了)。我整天都在用VBScript这样做:objExplorer.Document.GetElementsByTagName("area")(0).click

随机推荐