Функция x509.ParseCertificate

Функция x509.ParseCertificate выполняет парсинг DER-кодированного сертификата X.509 и возвращает указатель на структуру x509.Certificate. В качестве входного параметра функция принимает срез байтов []byte, содержащий данные сертификата в формате DER. В случае успешного разбора возвращается *x509.Certificate и nil в качестве ошибки. Если парсинг завершился неудачей, функция возвращает nil и ошибку с описанием проблемы.

Синтаксис

gox509.ParseCertificate(derBytes []byte) (*x509.Certificate, error)

Пример

Давайте разберем простой DER-сертификат и выведем его основные поля:

gopackage main

import (
  "crypto/x509"
  "encoding/pem"
  "fmt"
  "log"
)

func main() {
  // Пример PEM-сертификата (самоподписанный)
  pemCert := `-----BEGIN CERTIFICATE-----
  MIIDXTCCAkWgAwIBAgIJAKl4mKkqN1ZzMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
  BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
  aWRnaXRzIFB0eSBMdGQwHhcNMjQwMTAxMDAwMDAwWhcNMjUwMTAxMDAwMDAwWjBF
  MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
  ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
  CgKCAQEAu1SU1LfVLPHCYZM6YkLFiNmL6Q=="
  -----END CERTIFICATE-----`

  // Декодируем PEM
  block, _ := pem.Decode([]byte(pemCert))
  if block == nil {
    log.Fatal("failed to parse PEM block")
  }

  // Парсим сертификат
  cert, err := x509.ParseCertificate(block.Bytes)
  if err != nil {
    log.Fatal(err)
  }

  // Выводим информацию о сертификате
  fmt.Printf("Subject: %s\n", cert.Subject.CommonName)
  fmt.Printf("Issuer: %s\n", cert.Issuer.CommonName)
  fmt.Printf("Serial Number: %s\n", cert.SerialNumber.String())
  fmt.Printf("Not Before: %s\n", cert.NotBefore)
  fmt.Printf("Not After: %s\n", cert.NotAfter)
}

Результат выполнения кода:

go"Subject: "
"Issuer: "
"Serial Number: 16993836966523861691"
"Not Before: 2024-01-01 00:00:00 +0000 UTC"
"Not After: 2025-01-01 00:00:00 +0000 UTC"

Пример

Давайте проверим, что функция возвращает ошибку при попытке разобрать некорректные данные:

gopackage main

import (
  "crypto/x509"
  "fmt"
)

func main() {
  // Некорректные данные (не DER)
  invalidData := []byte("this is not a certificate")

  cert, err := x509.ParseCertificate(invalidData)
  if err != nil {
    fmt.Printf("Error: %v\n", err)
    fmt.Printf("Certificate is nil: %v\n", cert == nil)
  }
}

Результат выполнения кода:

go"Error: x509: malformed certificate"
"Certificate is nil: true"

Пример

Давайте извлечем открытый ключ из сертификата и проверим его тип:

gopackage main

import (
  "crypto/rsa"
  "crypto/x509"
  "encoding/pem"
  "fmt"
  "log"
)

func main() {
  pemCert := `-----BEGIN CERTIFICATE-----
  MIIDXTCCAkWgAwIBAgIJAKl4mKkqN1ZzMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
  BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
  aWRnaXRzIFB0eSBMdGQwHhcNMjQwMTAxMDAwMDAwWhcNMjUwMTAxMDAwMDAwWjBF
  MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
  ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
  CgKCAQEAu1SU1LfVLPHCYZM6YkLFiNmL6Q=="
  -----END CERTIFICATE-----`

  block, _ := pem.Decode([]byte(pemCert))
  if block == nil {
    log.Fatal("failed to parse PEM block")
  }

  cert, err := x509.ParseCertificate(block.Bytes)
  if err != nil {
    log.Fatal(err)
  }

  // Проверяем тип открытого ключа
  switch pub := cert.PublicKey.(type) {
  case *rsa.PublicKey:
    fmt.Printf("RSA public key with %d bits\n", pub.N.BitLen())
  default:
    fmt.Printf("Unknown key type: %T\n", pub)
  }
}

Результат выполнения кода:

go"RSA public key with 1024 bits"

Смотрите также

  • функцию x509.CreateCertificate,
    которая создает новый X.509 сертификат
  • функцию x509.ParsePKCS1PrivateKey,
    которая парсит PKCS1 закрытый ключ
  • функцию x509.ParsePKIXPublicKey,
    которая парсит открытый ключ в формате PKIX
  • функцию pem.Decode,
    которая декодирует PEM-блок для подготовки данных к парсингу