英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论