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

Viewed 133

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 Answers

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

Related