shadow1ng/fscan · error

parse certificate: %w

Error message

parse certificate: %w

What it means

When extracting the server's public key from the X.509 certificate chain carried in the GCC data, x509.ParseCertificate failed on the last certificate blob (AbCert) of the chain. The library wraps the underlying ASN.1 parse error with 'parse certificate: %w'.

Source

Thrown at libs/grdp/protocol/t125/gcc/gcc.go:415

type CertBlob struct {
	CbCert uint32 `struc:"little,sizeof=AbCert"`
	AbCert []byte `struc:"little"`
}
type X509CertificateChain struct {
	NumCertBlobs  uint32     `struc:"little,sizeof=CertBlobArray"`
	CertBlobArray []CertBlob `struc:"little"`
	Padding       []byte     `struc:"[12]byte"`
}

func (x *X509CertificateChain) GetPublicKey() (*rsa.PublicKey, error) {
	if len(x.CertBlobArray) == 0 {
		return nil, errors.New("empty certificate chain")
	}
	data := x.CertBlobArray[len(x.CertBlobArray)-1].AbCert
	cert, err := x509.ParseCertificate(data)
	if err != nil {
		return nil, fmt.Errorf("parse certificate: %w", err)
	}
	if cert.PublicKey == nil {
		var pubKeyInfo struct {
			Algorithm        pkix.AlgorithmIdentifier
			SubjectPublicKey asn1.BitString
		}
		_, err = asn1.Unmarshal(cert.RawSubjectPublicKeyInfo, &pubKeyInfo)
		if err != nil {
			return nil, fmt.Errorf("unmarshal public key info: %w", err)
		}
		rsaPublicKey, err := x509.ParsePKCS1PublicKey(pubKeyInfo.SubjectPublicKey.Bytes)
		if err != nil {
			return nil, fmt.Errorf("parse PKCS1 public key: %w", err)
		}
		return rsaPublicKey, nil
	}
	rsaPublicKey, ok := cert.PublicKey.(*rsa.PublicKey)
	if !ok {

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Hex-dump the AbCert blob and verify it starts with a DER SEQUENCE (0x30 0x82).
  2. Check the cert chain blob type; if the server sends PROPRIETARYCERT, this parser path does not apply.
  3. Update grdp to a version with broader server-certificate handling.
  4. Verify the ServerSecurityData/GCC parsing offsets are correct for this server's response.
Defensive patterns

Strategy: try-catch

Validate before calling

func looksLikeDER(b []byte) bool { return len(b) > 2 && b[0] == 0x30 }
if !looksLikeDER(certBlob) { return errors.New("cert blob is not DER X.509; likely proprietary cert type") }

Try / catch

pub, err := certChain.PublicKey()
if err != nil && strings.Contains(err.Error(), "parse certificate:") {
	return fmt.Errorf("server certificate unreadable (possibly proprietary cert format): %w", err)
}

Prevention

When it happens

Trigger: The AbCert bytes from CertBlobArray are not a valid DER-encoded X.509 certificate — truncated data, proprietary (non-X.509) certificate format (e.g. PROPRIETARYCERT in the server cert chain), or a parser misalignment.

Common situations: Old/quirky RDP servers that use proprietary certificate types instead of X509_CERTIFICATE_CHAIN; MTU/truncation issues in handshake capture; grdp parser bugs on exotic server configs.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/00360091d5b28f8e. Report an issue: GitHub.