如何在Go中解密由固定盐生成的字符串?

I have a large set of data that was encrypted with Jasypt and I need to decrypt it on Go. Both with fixed and random salt.

I found this repo with a working port of BasicTextEncryptor. It works fine for my data encrypted with password and random salt.

I tried replacing the random salt with my fixed string, while I don't get any errors, it doesn't return the actual encrypted content.

func FDecrypt(password, cipherText, salt string, obtenationIterations int) (string, error) {
    msgBytes, err := base64.StdEncoding.DecodeString(cipherText)
    if err != nil {
        return "", err
    }

    //salt := msgBytes[:8]
    encText := msgBytes[8:]

    dk, iv := getDerivedKey(password, salt, obtenationIterations)
    block, err := des.NewCipher(dk)

    if err != nil {
        return "", err
    }

    decrypter := cipher.NewCBCDecrypter(block, iv)
    decrypted := make([]byte, len(encText))
    decrypter.CryptBlocks(decrypted, encText)

    decryptedString := strings.TrimRight(string(decrypted), "\x01\x02\x03\x04\x05\x06\x07\x08")

    return decryptedString, nil
}

func getDerivedKey(password string, salt string, count int) ([]byte, []byte) {
    key := md5.Sum([]byte(password + salt))
    for i := 0; i < count - 1; i++ {
        key = md5.Sum(key[:])
    }
    return key[:8], key[8:]
}

I encrypted the following (in Jasypt) for tests:

  • Content: encryption test
  • Password: password
  • Salt: fixed_salt

The encryption result is: IcszAY8NRJf6ANt152Fifg==

When decrypting on Go with the above code I get: �p�=��

Any tips?

Sorry for answering my own question!

Before, I linked a Github repository with the code I was using as base to solve my problem. As Markus suggested in the comments, I opened an issue there. The repo owner (Lucas Sloan) gave me some tips. After checking the jasypt source and messing around with that code I posted earlier, I finally got a solution.

Here's the working code:

func Decrypt(password, cipherText, fixedSalt string, obtenationIterations int) (string, error) {
    msgBytes, err := base64.StdEncoding.DecodeString(cipherText)
    if err != nil {
        return "", err
    }

    salt := make([]byte, 8)
    copy(salt[:], fixedSalt)
    encText := msgBytes[:]

    dk, iv := getDerivedKey(password, salt, obtenationIterations)
    block, err := des.NewCipher(dk)

    if err != nil {
        return "", err
    }

    decrypter := cipher.NewCBCDecrypter(block, iv)
    decrypted := make([]byte, len(encText))
    decrypter.CryptBlocks(decrypted, encText)

    decryptedString := strings.TrimRight(string(decrypted), "\x01\x02\x03\x04\x05\x06\x07\x08")

    return decryptedString, nil
}

func getDerivedKey(password string, salt string, count int) ([]byte, []byte) {
    key := md5.Sum([]byte(password + salt))
    for i := 0; i < count - 1; i++ {
        key = md5.Sum(key[:])
    }
    return key[:8], key[8:]
}

I was missing two important points:

  1. Jasypt trims the salt to an 8 byte array:
salt := make([]byte, 8)
copy(salt[:], fixedSalt)
  1. When you encrypt with fixed salt, the salt doesn't get appended to the result, so you need to get the whole content when decrypting:
encText := msgBytes[:]

I made a PR to that repository, so you can just use that if you want. The package also has the encryption function (both with fixed and random salt): https://github.com/LucasSloan/passwordbasedencryption