猿问

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: message authentication 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

    }


    }


}


慕勒3428872
浏览 169回答 2
2回答

精慕HU

所以重点是:为了应用盐并导出,pbkdf2.Key()必须使用正确的密钥,如下所示nonceSpring Security 中的(或)大小Initialization Vector是 16 字节,而不是 12 字节go下面的摘录省略了错误处理,只是为了强调解决方案的本质:const nonceSize = 16func 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)}
随时随地看视频慕课网APP

相关分类

Go
我要回答