我正在嘗試將一個go 程式(https://github.com/mckael/samtv)移植到node.js,該程式可以透過“smartview”api 控制三星電視
程式中有一個「aes 加密」功能,我在移植到節點時遇到問題。
func (s *smartviewsession) aesencrypt(plaindata []byte) ([]byte, error) { //logrus.debugf("aesencrypt(%#v) : '%s'", plaindata, string(plaindata)) //logrus.debugf("session id: %d", s.sessionid) //logrus.debugf("session key: '%x'\n %v", string(s.sessionkey), s.sessionkey) // create cipher block block, err := aes.newcipher(s.sessionkey) if err != nil { return nil, err } bs := block.blocksize() //logrus.debugf("block size: %d", bs) // add padding padding := bs - len(plaindata)%bs padtext := bytes.repeat([]byte{byte(padding)}, padding) //logrus.debugf("padding: %d byte(s)", padding) plaindata = append(plaindata, padtext...) // encrypt ciphertext := make([]byte, len(plaindata)) for cipherrange := ciphertext; len(plaindata) > 0; { block.encrypt(cipherrange, plaindata[:bs]) plaindata = plaindata[bs:] cipherrange = cipherrange[bs:] } //logrus.debugf("ciphertext: %#v", ciphertext) return ciphertext, nil }
我現在面臨的問題是,我不知道使用了什麼algorythim,或者我需要在我的node.js函數中指定「初始向量」來自哪裡:
const SESSION_KEY = "59e8ca4b09f2a19ab5421cf55d604c7c"; var aesEncrypt = ((val, algo = "aes-256-cbc") => { let cipher = crypto.createCipheriv(algo, SESSION_KEY, IV); let encrypted = cipher.update(val, 'utf8', 'base64'); encrypted += cipher.final('base64'); return encrypted; });
我可以用 crypto.createcipher(...)
來代替嗎?但它已被棄用,而且感覺填充的東西很重要。
我對加密一無所知。 歡迎任何提示。
注意:在go函數中,s.sessionkey
與node.js中的session_key = "59e8ca4b09f2a19ab5421cf55d604c7c"
的值相同
go 程式碼在ecb 模式下套用aes 並使用pkcs#7 填入。 aes 變體隱含源自於金鑰大小,例如aes-128 用於 16 位元組金鑰。密文回傳為 []byte
。
在 nodejs 程式碼中,明確指定了 aes 變體以及模式,例如aes-128-ecb
。 ecb模式不套用iv,因此必須在createcipheriv()
中指定為null
。使用填入 pkcs#7(預設)。密文可以回傳為 buffer
,它最接近 []byte
。
發布的金鑰 59e8ca4b09f2a19ab5421cf55d604c7c
看起來像是十六進位編碼的金鑰,它是十六進位解碼的 16 位元組大,因此對應於 aes-128。十六進位解碼可以在 go 中使用 encoding/hex 套件來實現,例如與 hex.decodestring("59e8ca4b09f2a19ab5421cf55d604c7c")
。
在 ecb 模式下使用 aes-128(16 位元組金鑰)和 pkcs#7 填入的 nodejs 程式碼範例:
var crypto = require('crypto'); const SESSION_KEY = Buffer.from("59e8ca4b09f2a19ab5421cf55d604c7c", "hex"); var aesEncrypt = ((val, algo = "aes-128-ecb") => { let cipher = crypto.createCipheriv(algo, SESSION_KEY, null); return Buffer.concat([cipher.update(val, 'utf8'), cipher.final()]); }); var ciphertext = aesEncrypt("The quick brown fox jumps over the lazy dog"); console.log(ciphertext.toString('base64')); // T/uQforseVFkY93mqwpwCGVVnEFDTT5Gle8a8XUxCfOXCfYUo3uCJ/nwzCIJ9xqf
go 程式碼使用相同的金鑰(十六進位解碼)和明文以及密文的 base64 編碼給出相同的結果。
為了完整性:金鑰也可以採用utf-8 編碼,然後產生32 位元組金鑰,例如go 程式碼中的key := []byte("59e8ca4b09f2a19ab5421cf55d604c7c")
和const session_key = buffer.from("59e8ca4b09f2a19ab5421cf55d604c7c", "utf-8")
nodejs 程式碼。在 nodejs 程式碼中,也必須套用 aes-256-ecb
。最終,關鍵規範必須提供有關使用哪種編碼的資訊。
請注意,ecb 模式不安全。如今,通常使用經過身份驗證的加密,例如透過 gcm 模式。
以上是將 AES 加密功能移植到 node.js的詳細內容。更多資訊請關注PHP中文網其他相關文章!