func main() { var ( plaintext = "My super super super super duper long string to be encrypted" ivLen = 12 sLen, eLen int encrypted, decrypted, iv string bufEncrypt, bufDecrypt []byte ctxEncrypt, ctxDecrypt crypto.EVP_CIPHER_CTX ) // Setup error strings crypto.ERR_load_crypto_strings() // Add all OpenSSL algorithms crypto.OpenSSL_add_all_algorithms() // Load an OpenSSL config crypto.OPENSSL_config("") // Enable FIPS mode crypto.FIPS_mode_set(1) // Create new EVP_CIPHER_CTX instances ctxEncrypt, ctxDecrypt = crypto.EVP_CIPHER_CTX_new(), crypto.EVP_CIPHER_CTX_new() // Panic if either EVP_CIPHER_CTX fails to create if ctxEncrypt == nil { panic("ctxEncrypt is nil") } if ctxDecrypt == nil { panic("ctxDecrypt is nil") } // Initialize the EVP_CIPHER_CTX instances crypto.EVP_CIPHER_CTX_init(ctxEncrypt) crypto.EVP_CIPHER_CTX_init(ctxDecrypt) // Create random IV for nondeterministic encryption buf := make([]byte, ivLen) _, e := rand.Read(buf) if e != nil { panic(e) } iv = string(buf) // Pass the IV into the encrypted string to be used when decoding encrypted = iv // Print plaintext string fmt.Printf("plaintext: %s\n", plaintext) /* Encrypting a string */ // Initialize the ctxEncrypt context for encryption crypto.EVP_EncryptInit_ex(ctxEncrypt, crypto.EVP_aes_256_cbc(), crypto.SwigcptrStruct_SS_engine_st(0), "somekey", iv) // Make a buffer with enough size for the plaintext plus one block bufEncrypt = make([]byte, len(plaintext)+ctxEncrypt.GetCipher().GetBlock_size()) // Update the cipher with some content crypto.EVP_EncryptUpdate(ctxEncrypt, bufEncrypt, &sLen, plaintext, len(plaintext)) // Append encrypted data to encrypted string encrypted += string(bufEncrypt[:sLen]) // Finalize the cipher to flush any remaining data crypto.EVP_EncryptFinal_ex(ctxEncrypt, bufEncrypt, &eLen) // Append any remaining data to the encrypted string encrypted += string(bufEncrypt[:eLen]) // Clean up the EVP_CIPHER_CTX crypto.EVP_CIPHER_CTX_cleanup(ctxEncrypt) /* Decrypting a string */ // Grab the IV from the encrypted string iv = string([]byte(encrypted)[:ivLen]) // Slice the encrypted string to begin after the iv encrypted = encrypted[ivLen:] // Initialize the ctxDecrypt context for decryption crypto.EVP_DecryptInit_ex(ctxDecrypt, crypto.EVP_aes_256_cbc(), crypto.SwigcptrStruct_SS_engine_st(0), "somekey", iv) // Make a buffer the exact size of the encrypted text bufDecrypt = make([]byte, len(encrypted)) // Update the cipher with the encrypted string crypto.EVP_DecryptUpdate(ctxDecrypt, bufDecrypt, &sLen, encrypted, len(encrypted)) // Append decrypted data to decrypted string decrypted = string(bufDecrypt[:sLen]) // Finalize the cipher to flush any remaining data crypto.EVP_DecryptFinal_ex(ctxDecrypt, bufDecrypt, &eLen) // Append any remaining data to decrypted string decrypted += string(bufDecrypt[:eLen]) // Print decoded string fmt.Printf("decrypted: %s\n", decrypted) // Clean up the EVP_CIPHER_CTX crypto.EVP_CIPHER_CTX_cleanup(ctxDecrypt) }
}) It("Initializes and deallocates directly", func() { ctx := Malloc_EVP_MD_CTX() Expect(EVP_DigestInit(ctx, EVP_sha256())).To(Equal(1)) buf := make([]byte, 50) var l uint Expect(EVP_DigestFinal(ctx, buf, &l)).To(Equal(1)) }) }) Context("With FIPS mode enabled", func() { var ctx EVP_MD_CTX BeforeEach(func() { crypto.FIPS_mode_set(1) Expect(crypto.FIPS_mode()).To(Equal(1)) ctx = Malloc_EVP_MD_CTX() Expect(ctx).NotTo(BeNil()) EVP_MD_CTX_init(ctx) }) AfterEach(func() { crypto.FIPS_mode_set(0) Expect(crypto.FIPS_mode()).To(Equal(0)) EVP_MD_CTX_cleanup(ctx) Free_EVP_MD_CTX(ctx) }) It("Allows use of SHA* but disallows MD5", func() { Expect(EVP_DigestInit_ex(ctx, EVP_md5(), SwigcptrStruct_SS_engine_st(0))).To(Equal(0))