i++

プログラム系のメモ書きなど

golang : RSA キーを含む pem ファイルの読み込み

秘密鍵の読み込み

RSA秘密鍵の pem ファイルは BEGIN RSA PRIVATE KEY で始まる場合(PKCS#1)と BEGIN PRIVATE KEY で始まる場合(PKCS#8)があり、前者の場合は x509.ParsePKCS1PrivateKey を、後者の場合は x509.ParsePKCS8PrivateKey を使ってパースする必要がある。

func readRsaPrivateKey(pemFile string) (*rsa.PrivateKey, error) {
    bytes, err := ioutil.ReadFile(pemFile)
    if err != nil {
        return nil, err
    }

    block, _ := pem.Decode(bytes)
    if block == nil {
        return nil, errors.New("invalid private key data")
    }

    var key *rsa.PrivateKey
    if block.Type == "RSA PRIVATE KEY" {
        key, err = x509.ParsePKCS1PrivateKey(block.Bytes)
        if err != nil {
            return nil, err
        }
    } else if block.Type == "PRIVATE KEY" {
        keyInterface, err := x509.ParsePKCS8PrivateKey(block.Bytes)
        if err != nil {
            return nil, err
        }
        var ok bool
        key, ok = keyInterface.(*rsa.PrivateKey)
        if !ok {
            return nil, errors.New("not RSA private key")
        }
    } else {
        return nil, fmt.Errorf("invalid private key type : %s", block.Type)
    }

    key.Precompute()

    if err := key.Validate(); err != nil {
        return nil, err
    }

    return key, nil
}
公開鍵の読み込み
func readRsaPublicKey(path string) (*rsa.PublicKey, error) {
    bytes, err := ioutil.ReadFile(path)
    if err != nil {
        return nil, err
    }

    block, _ := pem.Decode(bytes)
    if block == nil {
        return nil, errors.New("invalid public key data")
    }
    if block.Type != "PUBLIC KEY" {
        return nil, fmt.Errorf("invalid public key type : %s", block.Type)
    }

    keyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
        return nil, err
    }

    key, ok := keyInterface.(*rsa.PublicKey)
    if !ok {
        return nil, errors.New("not RSA public key")
    }

    return key, nil
}
参考