How to encrypt a file so that OpenSSL can decrypt it without providing the IV manually

huangapple go评论75阅读模式
英文:

How to encrypt a file so that OpenSSL can decrypt it without providing the IV manually

问题

我想用AES加密一个文件,就像openssl enc命令一样,这样当我想解密它时就不需要手动提供IV。

英文:

I want to encrypt a file with AES the same way openssl enc command does, so when I want to decrypt it there won't be need for providing IV manually.

答案1

得分: 2

为了解密一个AES加密的文件,你需要同时拥有密钥和初始化向量(IV)。IV并不是一个秘密,通常存储在加密文件中。

OpenSSL使用一个密钥派生函数,使用提供的密码和一个随机盐来生成这两个值。然后,在加密过程中,它将盐存储在文件头部,并添加*Salted__*前缀,以便在解密时可以与密码一起使用,生成相同的密钥和IV。

你可以使用以下代码进行解密:

package main

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"crypto/sha256"
	"io"
	"os"
	"golang.org/x/crypto/pbkdf2"
)

func main() {
	keySize := 32
	password := []byte("TESTPASSWORD1234TESTPASSWORD1234")
	bReader, err := os.Open("doc-encrypted.docx")
	defer bReader.Close()
	if err != nil {
		panic(err)
	}

	header := make([]byte, 16)
	if _, err := io.ReadFull(bReader, header); err != nil {
		panic(err)
	}

	salt := header[8:16]
	computed := pbkdf2.Key(password, salt, 10000, keySize+aes.BlockSize, sha256.New)
	key := computed[:keySize]
	iv := computed[keySize:]

	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}
	stream := cipher.NewOFB(block, iv)

	bWriter, err := os.Create("doc-decrypted.docx")
	if err != nil {
		panic(err)
	}
	defer bWriter.Close()

	sReader := &cipher.StreamReader{S: stream, R: bReader}
	if _, err := io.Copy(bWriter, sReader); err != nil {
		panic(err)
	}
}

你可以使用以下命令解密:

openssl enc -in doc-encrypted.docx -out doc-decrypted.docx -d -aes-256-ofb -pbkdf2 -pass pass:TESTPASSWORD1234TESTPASSWORD1234

请注意,这只是一个演示用途的代码,实际使用时需要进行适当的错误处理和安全性考虑。

英文:

In order to decrypt an AES encrypted file you need both key and IV. IV is not a secret and is usually store at the encrypted file.

OpenSSL uses a key derivation function to generate these two using the provided password and a random salt. then after encryption it stores the salt at the header of the file with Salted__ prefix, so at the decryption it could use it along with the password to produce the same key and IV.

package main

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"crypto/sha256"
	"io"
	"os"
	"golang.org/x/crypto/pbkdf2"
)

func main() {

	keySize := 32;
    // its only for demonstration purpose
	password := []byte("TESTPASSWORD1234TESTPASSWORD1234");
	bReader, err := os.Open("doc.docx")
	defer bReader.Close();
	if err != nil {
		panic(err)
	}

	salt := make([]byte, 8)
	if _, err := io.ReadFull(rand.Reader, salt[:]); err != nil {
		panic(err)
	}

	computed := pbkdf2.Key(password, salt, 10000, keySize + aes.BlockSize , sha256.New)
	key := computed[:keySize]
	iv := computed[keySize:]

	block, err := aes.NewCipher(key)                                    
	if err != nil {
		panic(err)
	}
	stream := cipher.NewOFB(block, iv)

	bWriter, err := os.Create("doc-encrypted.docx")
	if err != nil {
		panic(err)
 	}
	defer bWriter.Close()

	prefix := []byte("Salted__");
	header := append(prefix[:], salt...);
  bWriter.Write(header)
	sWriter := &cipher.StreamWriter{S: stream, W: bWriter}
	if _, err := io.Copy(sWriter, bReader); err != nil {
		panic(err)
	}

}

and you can decrypt it with openssl enc -in doc-encrypted.docx -out doc-decrypted.docx -d -aes-256-ofb -pbkdf2 -pass pass:TESTPASSWORD1234TESTPASSWORD1234

huangapple
  • 本文由 发表于 2022年8月12日 16:20:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/73331215.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定