Spring Security 加密字符串 - Go 中解密失败
来源:stackoverflow
2024-04-05 11:42:34
0浏览
收藏
Golang不知道大家是否熟悉?今天我将给大家介绍《Spring Security 加密字符串 - Go 中解密失败》,这篇文章主要会讲到等等知识点,如果你在看完本篇文章后,有更好的建议或者发现哪里有问题,希望大家都能积极评论指出,谢谢!希望我们能一起加油进步!
问题内容
加密将在客户端使用以下基于 spring security-encryptors 的代码完成:
package at.wrwks.pipe.baumgmt.component.documentpreview;
import static java.nio.charset.standardcharsets.utf_8;
import java.net.urlencoder;
import java.util.base64;
import org.springframework.security.crypto.codec.hex;
import org.springframework.security.crypto.encrypt.encryptors;
import org.springframework.stereotype.component;
@component
public class secureresourceurlcomposer {
public string compose(final string resource) {
final var salt = new string(hex.encode("salt".getbytes(utf_8)));
final var encryptor = encryptors.stronger("password", salt);
final var encryptedresource = encryptor.encrypt(resource.getbytes(utf_8));
final var base64encodedencryptedresource = base64.getencoder().encodetostring(encryptedresource);
final var urlencodedbase64encodedencryptedresource = urlencoder.encode(base64encodedencryptedresource, utf_8);
return "https://target" + "?resource=" + urlencodedbase64encodedencryptedresource;
}
}
示例资源:aresource
url 和 base64 编码输出:https://target?resource=yeadq1toefbctkcaetjmw7zlydk4fa2waaspzsfqqxaxiq7bmuaruye%3d
解密失败,并显示 cipher: messageauthentication failed 在以下用 go 编写的后端代码中,位于 gcm.open:
func decryptgcmaes32(ciphertext, key string) (plaintext string, err error) {
if len(key) != 32 {
msg := fmt.sprintf("unexpected key length (!= 32) '%s' %d", key, len(key))
err = errors.new(msg)
log.warn(err)
sentry.captureexception(err)
return
}
keybytes := []byte(key)
c, err := aes.newcipher(keybytes)
if err != nil {
log.warn("couldn't create a cipher block", err)
sentry.captureexception(err)
return
}
gcm, err := cipher.newgcm(c)
if err != nil {
log.warn("couldn't wrap in gcm mode", err)
sentry.captureexception(err)
return
}
noncesize := gcm.noncesize()
if len(ciphertext) < noncesize {
msg := fmt.sprintf("ciphertext shorter than nonce size %d < %d", len(ciphertext), noncesize)
err = errors.new(msg)
log.warn(err)
sentry.captureexception(err)
return
}
ciphertextbytes := []byte(ciphertext)
nonce, ciphertextbytes := ciphertextbytes[:noncesize], ciphertextbytes[noncesize:]
plaintextbytes, err := gcm.open(nil, nonce, ciphertextbytes, nil)
if err != nil {
log.warn("couldn't decode", err)
sentry.captureexception(err)
return
}
plaintext = string(plaintextbytes)
return
}
如果 iv 的加密和解密相同,则 go 中的以下测试仅有效
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/sha1"
"golang.org/x/crypto/pbkdf2"
"log"
"testing"
)
var iv = make([]byte, 12)
func TestCrypto(t *testing.T) {
rand.Read(iv)
encrypted, _ := encrypt("aResource")
if decrypted, err := decrypt(encrypted); err != nil {
log.Println(err)
} else {
log.Printf("DECRYPTED: %s\n", decrypted)
}
}
func encrypt(secret string) (result []byte, err error) {
salt := []byte("salt")
key := pbkdf2.Key([]byte("b0226e4e9bef40d4b8aed039c208ae3e"), salt, 1024, 16, sha1.New)
b, err := aes.NewCipher(key)
aesgcm, err := cipher.NewGCM(b)
result = aesgcm.Seal(nil, iv, []byte(secret), nil)
return
}
func decrypt(ciphertext []byte) (result string, err error) {
salt := []byte("salt")
key := pbkdf2.Key([]byte("b0226e4e9bef40d4b8aed039c208ae3e"), salt, 1024, 16, sha1.New)
b, err := aes.NewCipher(key)
aesgcm, err := cipher.NewGCM(b)
decrypted, err := aesgcm.Open(ciphertext[:0], iv, ciphertext, nil)
result = string(decrypted)
return
}解决方案
所以要点:
- 为了应用盐并派生正确的密钥
pbkdf2.key()必须如下所示使用 - spring security 中的
nonce(或initialization vector)大小为 16 个字节,而go中为 12 个字节
下面的摘录省略了错误处理,只是为了强调解决方案的本质:
const noncesize = 16
func decryptwithaes256gcmpbkdf2(cipherbytes []byte, password string, salt string) (string) {
key := pbkdf2.key([]byte(password), []byte(salt), 1024, 32, sha1.new)
c, _ := aes.newcipher(key)
gcm, _ := cipher.newgcmwithnoncesize(c, noncesize)
plaintextbytes, _ := gcm.open(nil, cipherbytes[:noncesize], cipherbytes[noncesize:], nil)
return string(plaintextbytes)
}
虽然问题涉及“更强”的解密。
我想给出一个“标准”解密的完整示例,以扩展之前的答案。
就我而言,任务是在 go 中实现以下 java 代码:
import org.springframework.security.crypto.encrypt.encryptors;
import org.springframework.security.crypto.encrypt.textencryptor;
...
private static final string salt = "123456789abcdef0"; // hex
public static string decrypt(final string encryptedtext, final string password) {
textencryptor encryptor = encryptors.text(password, salt);
return encryptor.decrypt(encryptedtext);
}
翻译成 go 的代码:
import (
"crypto/aes"
"crypto/cipher"
"crypto/sha1"
"encoding/hex"
"fmt"
"strings"
"golang.org/x/crypto/pbkdf2"
)
func decryptWithAes256CbcPbkdf2(cipherBytes []byte, passwordBytes []byte, saltBytes []byte) string {
key := pbkdf2.Key(passwordBytes, saltBytes, 1024, 32, sha1.New)
if len(key) != 32 {
panic(fmt.Sprintf("Unexpected key length (!= 32) '%s' %d", key, len(key)))
}
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
if len(cipherBytes) < aes.BlockSize {
panic("ciphertext too short")
}
iv := cipherBytes[:aes.BlockSize]
cipherBytes = cipherBytes[aes.BlockSize:]
if len(cipherBytes)%aes.BlockSize != 0 {
panic("ciphertext is not a multiple of the block size")
}
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(cipherBytes, cipherBytes)
return strings.Trim(string(cipherBytes), "\b")
}
func main() {
cipherText := "05589d13fe6eedceae78fe099eed2f6b238ac7d4dbb62c281ccdc9401b24bb0c"
cipherBytes, _ := hex.DecodeString(cipherText)
passwordText := "12345"
passwordBytes := []byte(passwordText)
saltText := "123456789abcdef0"
saltBytes, _ := hex.DecodeString(saltText)
plainText := decryptWithAes256CbcPbkdf2(cipherBytes, passwordBytes, saltBytes)
fmt.Println(plainText)
}今天关于《Spring Security 加密字符串 - Go 中解密失败》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!
版本声明
本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
交换指针:相当于 `std::unique_ptr::swap`
- 上一篇
- 交换指针:相当于 `std::unique_ptr::swap`
- 下一篇
- 使用闭包在 Go 中编写下一个排列,我的代码有什么问题
查看更多
最新文章
-
- Golang · Go问答 | 7小时前 | go · RGBA image ColorModel At
- Go image 怎样读取不同颜色模型的像素
- 291浏览 收藏
-
- Golang · Go问答 | 7小时前 |
- Go 怎样把 pprof 挂到独立 ServeMux
- 491浏览 收藏
-
- Golang · Go问答 | 7小时前 |
- Go embed FS 打开不存在资源时怎样保留错误上下文
- 141浏览 收藏
-
- Golang · Go问答 | 7小时前 |
- Go template.Funcs 怎样在 ParseFS 前注册自定义函数
- 406浏览 收藏
-
- Golang · Go问答 | 7小时前 |
- Go XML Decoder Strict 关闭后适合什么兼容场景
- 412浏览 收藏
-
- Golang · Go问答 | 7小时前 |
- Go 怎样读取子进程资源使用量
- 373浏览 收藏
-
- Golang · Go问答 | 7小时前 |
- Go os/user Current 和 Lookup 怎样选择
- 171浏览 收藏
-
- Golang · Go问答 | 7小时前 | 权限 · Go问答 · Go Unix Socket UnixConn 对端凭据 SO_PEERCRED x/sys/unix
- Go Unix socket 怎样读取对端凭据
- 302浏览 收藏
-
- Golang · Go问答 | 7小时前 |
- Go Unix 数据报套接字怎样处理报文边界
- 336浏览 收藏
-
- Golang · Go问答 | 7小时前 |
- Go 项目怎样为 HTTP/3 客户端划分可选依赖
- 471浏览 收藏
-
- Golang · Go问答 | 7小时前 |
- Go HTTP/2 异常怎样用 GODEBUG 获取线索
- 366浏览 收藏
查看更多
课程推荐
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
查看更多
AI推荐
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 478次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 535次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 554次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 506次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 327次使用
查看更多
相关文章
-
- 用Nginx反向代理部署go写的网站。
- 2023-01-17 502浏览
-
- GoLand调式动态执行代码
- 2023-01-13 502浏览
-
- Go crypto/rand.Text 的长度为什么不是固定字符数
- 2026-10-04 501浏览
-
- Go strings.ToValidUTF8 清洗日志内容的边界
- 2026-10-03 501浏览
-
- Go tls.GetCertificate 为什么收不到空 ServerName 请求
- 2026-09-27 501浏览
