shadow1ng/fscan · error
unsupported public key type: %T
Error message
unsupported public key type: %T
What it means
When the certificate does carry a non-nil PublicKey, the library asserts it is an *rsa.PublicKey via a type assertion. Any other key type (ECDSA, Ed25519, etc.) fails the assertion and yields 'unsupported public key type: %T'. grdp only supports RSA server keys because the RDP standard security handshake uses RSA for the client random exchange.
Source
Thrown at libs/grdp/protocol/t125/gcc/gcc.go:434
}
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 {
return nil, fmt.Errorf("unsupported public key type: %T", cert.PublicKey)
}
return rsaPublicKey, nil
}
func (x *X509CertificateChain) Verify() bool {
return true
}
func (x *X509CertificateChain) Encrypt() []byte {
//todo
return nil
}
func (x *X509CertificateChain) Unpack(r io.Reader) error {
return struc.Unpack(r, x)
}
type ServerCoreData struct {
RdpVersion VERSION `struc:"uint32,little"`
ClientRequestedProtocol uint32 `struc:"little"`
EarlyCapabilityFlags uint32 `struc:"little"`View on GitHub (pinned to 95cc12e753)
Solutions
- Issue an RSA-based certificate for the RDP host (2048-bit+ RSA) — RSA is the expected RDP server key type.
- Check cert.PublicKey's dynamic type via the %T text in the error to confirm which algorithm was found.
- Extend the library to support the key type if you control the codebase and the protocol allows it.
- Force the server to use standard RDP security/NLA with RSA keys.
Defensive patterns
Strategy: type-guard
Validate before calling
switch cert.PublicKey.(type) {
case *rsa.PublicKey:
// ok
default:
return errors.New("server certificate key must be RSA")
} Type guard
func isRSAPublicKey(cert *x509.Certificate) bool {
_, ok := cert.PublicKey.(*rsa.PublicKey)
return ok
} Try / catch
pub, err := certChain.PublicKey()
if err != nil && strings.Contains(err.Error(), "unsupported public key type") {
return fmt.Errorf("host uses non-RSA server key; reissue RSA cert or skip host: %v", err)
} Prevention
- Issue RSA (>=2048-bit) certificates on RDP servers.
- Pre-check cert.PublicKey type before key-exchange code paths.
- Record %T in triage logs to identify offending algorithms.
- Avoid hardened ECC-only TLS policies on RDP endpoints.
When it happens
Trigger: Connecting to an RDP host whose certificate uses an ECDSA/Ed25519 public key instead of RSA; the GCC cert chain parses fine but the key type is incompatible with grdp's key exchange.
Common situations: Modern/custom TLS configurations or non-Windows RDP implementations issuing ECC certificates; hardened environments that mandate ECC.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- parse PKCS1 public key: %w
- empty certificate chain
- Unhandled saveSessionInfo type 0x%x
- parse certificate: %w
- unmarshal public key info: %w
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/b6d20f25ed891078.
Report an issue: GitHub.