英文:
transforming strings in a golang struct
问题
我有一个AES加密的JSON文件。结构如下:
{
"username": "asdf123ASLdf3",
"password": "elisjdvo4etQW"
}
还有一个用于保存这些值的结构体:
type Secrets struct {
Username string `json:"username"`
Password string `json:"password"`
}
将加密的JSON值加载到结构体中很容易,但我真正想要的是一个包含未加密值的结构体。
因此,对于每个值,我想要运行一个函数:
aesDecrypt(key string, value string) string
我可以在第一次加载时完成这个操作,或者将所有内容移动到一个新的结构体中。
我希望避免重复使用JSON键或字段名。
怎样才能做到最好呢?
(也欢迎其他在Go中管理加密密钥的方法)
英文:
I've got a json file of AES encrypted secrets. The structure is:
{
"username": "asdf123ASLdf3",
"password": "elisjdvo4etQW"
}
And a struct to hold these values
type Secrets struct {
Username string `json:"username"`
Password string `json:"password"`
}
It's easy to load the encrypted json values into the struct, but what I really want is a struct with the unencrypted values.
So, for each value, I'd like to run it though a function:
aesDecrypt(key string, value string) string
I'm happy to have this done on the first load, or to move everything over into a new struct.
I would like to avoid repeating the json keys or the field names.
What's the best way to do this?
(Also open to other ways to manage encrypted secrets in Go)
答案1
得分: 2
一种选择是定义一个自定义的JSON解析器。另一种选择是,正如你提到的,将其复制到另一个结构体中。
- 实现Unmarshaler接口
关键的洞察力是知道你可以通过实现Unmarshaler接口来覆盖json.Unmarshal
的行为。在我们的情况下,这意味着定义一个函数func (ss *Secrets) UnmarshalJSON(bb []byte) error
,当你尝试将任何JSON解析为Secrets
时,它将执行AES解密。
package main
import "fmt"
import "encoding/json"
type Secrets struct {
Username string `json:"username"`
Password string `json:"password"`
}
func main() {
jj := []byte(`{
"username": "asdf123ASLdf3",
"password": "elisjdvo4etQW"
}`)
var ss Secrets
json.Unmarshal(jj, &ss)
fmt.Println(ss)
}
func aesDecrypt(key, value string) string {
return fmt.Sprintf("'%s' decrypted with key '%s'", value, key)
}
func (ss *Secrets) UnmarshalJSON(bb []byte) error {
var objmap map[string]*string
err := json.Unmarshal(bb, &objmap)
ss.Username = aesDecrypt("my key", *objmap["password"])
ss.Password = aesDecrypt("my key", *objmap["username"])
return err
}
这将输出一个Secrets
结构体:
{'elisjdvo4etQW' decrypted with key 'my key'
'asdf123ASLdf3' decrypted with key 'my key'}
- 复制到另一个结构体
每次需要解密JSON时,你可以简单地创建一个新的Secrets
结构体。如果你经常这样做,或者不需要中间状态,这可能会很繁琐。
package main
import "fmt"
import "encoding/json"
type Secrets struct {
Username string `json:"username"`
Password string `json:"password"`
}
func main() {
jj := []byte(`{
"username": "asdf123ASLdf3",
"password": "elisjdvo4etQW"
}`)
var ss Secrets
json.Unmarshal(jj, &ss)
decoded := Secrets{
aesDecrypt(ss.Username, "my key"),
aesDecrypt(ss.Password, "my key")}
fmt.Println(decoded)
}
func aesDecrypt(key, value string) string {
return fmt.Sprintf("'%s' decrypted with key '%s'", value, key)
}
这与上面的输出相同:
{'elisjdvo4etQW' decrypted with key 'my key'
'asdf123ASLdf3' decrypted with key 'my key'}
显然,你应该使用不同版本的aesDecrypt
,我的只是一个虚拟的。并且,像往常一样,你应该在自己的代码中实际检查返回的错误。
英文:
One option is to define a custom JSON Unmarshaler. Another is, as you mention, copy it to another struct.
-
Implementing the Unmarshaler interface
The key insight is knowing that you can override
json.Unmarshal
's
behaviour by implementing the Unmarshaler interface. In our
case, that means defining a functionfunc (ss *Secrets)
that will do the AES Decryption when
UnmarshalJSON(bb []byte) error
you try to unmarshal any JSON to aSecrets
.package main import "fmt" import "encoding/json" type Secrets struct { Username string `json:"username"` Password string `json:"password"` } func main() { jj := []byte(`{ "username": "asdf123ASLdf3", "password": "elisjdvo4etQW" }`) var ss Secrets json.Unmarshal(jj, &ss) fmt.Println(ss) } func aesDecrypt(key, value string) string { return fmt.Sprintf("'%s' decrypted with key '%s'", value, key) } func (ss *Secrets) UnmarshalJSON(bb []byte) error { var objmap map[string]*string err := json.Unmarshal(bb, &objmap) ss.Username = aesDecrypt("my key", *objmap["password"]) ss.Password = aesDecrypt("my key", *objmap["username"]) return err }
This outputs a
Secrets
struct:{'elisjdvo4etQW' decrypted with key 'my key' 'asdf123ASLdf3' decrypted with key 'my key'}
-
Copying to another struct
You could simply make a new
Secrets
struct every time you need to
decrypt the JSON. This could be tedious if you do it alot, or if you
have no need for the intermediate state.package main import "fmt" import "encoding/json" type Secrets struct { Username string `json:"username"` Password string `json:"password"` } func main() { jj := []byte(`{ "username": "asdf123ASLdf3", "password": "elisjdvo4etQW" }`) var ss Secrets json.Unmarshal(jj, &ss) decoded := Secrets{ aesDecrypt(ss.Username, "my key"), aesDecrypt(ss.Password, "my key")} fmt.Println(decoded) } func aesDecrypt(key, value string) string { return fmt.Sprintf("'%s' decrypted with key '%s'", value, key) }
Check it out at Go Playground.
This has the same output as above:
{'elisjdvo4etQW' decrypted with key 'my key' 'asdf123ASLdf3' decrypted with key 'my key'}
Obviously, you would use a different version of aesDecrypt
, mine's
just a dummy. And, as always, you should actually be checking the
returned errors in your own code.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论