Перейти использовать для записи в файл байтов оптимизировать в Голанге - PullRequest
0 голосов
/ 10 октября 2018

У меня есть следующая программа, которая печатает информацию о каждом сертификате в файле .pem:

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)
    }
}

это работает, но обратите внимание, что каждая строка отдельно записывает в файл.Это кажется немного расточительным, но я не уверен насчет опций в Go ... создать массив ... вырезать его из сертификата ... другой цикл for ...

ВОПРОС

Вместо f.Write () в каждой строке, какой правильный или альтернативный подход в Go?

Вместо использования сертификата. *, Я должен захватыватьэти данные в структуру или массив?

Последующие действия

Допустим, последняя запись или любая запись не удалась, Go откатывает изменения или последняя запись не записываетсяв файл?Это должна быть запись «все или ничего».

(это я учусь, как и я, спасибо за вашу помощь)

1 Ответ

0 голосов
/ 10 октября 2018

Самый простой способ записи в буфер в памяти - это использование пакета bytes, который обеспечивает тип Buffer.Поскольку Buffer реализует интерфейс Writer , вы можете обновить Write вызовы, чтобы использовать вместо них Buffer, а затем использовать метод Buffer.WriteTo для записинакопленные данные в файл.Вот как это выглядит с комбинированными циклами:

package main

import (
    "bytes"
    "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)
    }

    //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)
    }

    var buf bytes.Buffer
    for {
        var certDERBlock *pem.Block
        certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
        if certDERBlock == nil {
            break
        }

        if certDERBlock.Type == "CERTIFICATE" {
            cert, err := x509.ParseCertificate(certDERBlock.Bytes)
            if err != nil {
                log.Println(err)
                continue
            }

            //APPEND CERT INFO TO FILE
            //VERSION
            if _, err := buf.Write([]byte(strconv.Itoa(cert.Version))); err != nil {
                log.Fatal(err)
            }
            //KEY ID
            if _, err := buf.Write(cert.SubjectKeyId); err != nil {
                log.Fatal(err)
            }
            //SIGNATURE LENGTH
            if _, err := buf.Write([]byte(strconv.Itoa(SignatureLength))); err != nil {
                log.Fatal(err)
            }
            //COMMON NAME
            if _, err := buf.Write([]byte(cert.Subject.CommonName)); err != nil {
                log.Fatal(err)
            }
        }
    } //end for

    // write data accumulated in buf out to f
    buf.WriteTo(f)

    //CLOSE THE FILE
    if err := f.Close(); err != nil {
        log.Fatal(err)
    }
}
...