I have the following program that prints out information about each certificate in a .pem
file:
package main
import (
"crypto/x509"
"encoding/pem"
"io/ioutil"
"log"
"os"
"strconv"
)
func main() {
//for dev purposes set to 256
const SignatureLength int = 256
certPEMBlock, err := ioutil.ReadFile("testsign.crt")
if err != nil {
log.Fatal(err)
}
var blocks [][]byte
for {
var certDERBlock *pem.Block
certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
if certDERBlock == nil {
break
}
if certDERBlock.Type == "CERTIFICATE" {
blocks = append(blocks, certDERBlock.Bytes)
}
} //end for
//OPEN FILE TO APPEND CERT INFORMATION INTO
f, err := os.OpenFile("appendMe.txt", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
for _, block := range blocks {
cert, err := x509.ParseCertificate(block)
if err != nil {
log.Println(err)
continue
}
//APPEND CERT INFO TO FILE
//VERSION
if _, err := f.Write([]byte(strconv.Itoa(cert.Version))); err != nil {
log.Fatal(err)
}
//KEY ID
if _, err := f.Write(cert.SubjectKeyId); err != nil {
log.Fatal(err)
}
//SIGNATURE LENGTH
if _, err := f.Write([]byte(strconv.Itoa(SignatureLength))); err != nil {
log.Fatal(err)
}
//COMMON NAME
if _, err := f.Write([]byte(cert.Subject.CommonName)); err != nil {
log.Fatal(err)
}
} //end for
//CLOSE THE FILE
if err := f.Close(); err != nil {
log.Fatal(err)
}
}
it works, but notice that each line separately writes to the file. That seems a bit wasteful, but I am not clear about options in Go...do I create an array...do I slice it from the cert...another for loop...
QUESTION
Instead of f.Write() on each line, what is the proper or alternative approach in Go?
Instead of using the cert.*, should I be capturing that data into a struct or array?
Follow up
let's say the last write or any write fails, does Go roll back changes or does last write not get written to the file? This needs to be an all or nothing write.
(this is me learning as I do, thanks for your help)