{"record":{"id":"5a932cc46c1539c9","repo":"slackhq/nebula","slug":"invalid-asn-1","errorCode":null,"errorMessage":"invalid ASN.1","messagePattern":"invalid ASN\\.1","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cert/p256/p256.go","lineNumber":97,"sourceCode":"\n\tnewR, newS, err := swap(r, s)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn encodeSignature(newR, newS)\n}\n\n// parseSignature taken exactly from crypto/ecdsa/ecdsa.go\nfunc parseSignature(sig []byte) (r, s []byte, err error) {\n\tvar inner cryptobyte.String\n\tinput := cryptobyte.String(sig)\n\tif !input.ReadASN1(&inner, asn1.SEQUENCE) ||\n\t\t!input.Empty() ||\n\t\t!inner.ReadASN1Integer(&r) ||\n\t\t!inner.ReadASN1Integer(&s) ||\n\t\t!inner.Empty() {\n\t\treturn nil, nil, errors.New(\"invalid ASN.1\")\n\t}\n\treturn r, s, nil\n}\n\nfunc encodeSignature(r, s []byte) ([]byte, error) {\n\tvar b cryptobyte.Builder\n\tb.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {\n\t\taddASN1IntBytes(b, r)\n\t\taddASN1IntBytes(b, s)\n\t})\n\treturn b.Bytes()\n}\n\n// addASN1IntBytes encodes in ASN.1 a positive integer represented as\n// a big-endian byte slice with zero or more leading zeroes.\nfunc addASN1IntBytes(b *cryptobyte.Builder, bytes []byte) {\n\tfor len(bytes) > 0 && bytes[0] == 0 {\n\t\tbytes = bytes[1:]","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cert/p256/p256.go#L79-L115","documentation":"parseSignature in cert/p256/p256.go raises 'invalid ASN.1' when a P-256 signature blob cannot be parsed as a DER SEQUENCE containing exactly two integers (r, s). This is a low-level Go error, not a sentinel, produced when the cryptobyte ASN.1 read of the signature structure fails.","triggerScenarios":"Calling IsNormalized, Normalize, or Swap with a byte slice that is not a well-formed ASN.1 DER ECDSA signature — wrong length, wrong tag, trailing bytes, or missing/oversized integers.","commonSituations":"Signatures received over the wire corrupted or truncated; raw (r||s) fixed-width signatures supplied where DER is expected (or vice versa); signatures from a library using a different encoding convention.","solutions":["Confirm the signature bytes are DER-encoded ASN.1 (SEQUENCE of two INTEGERs), not raw 64-byte r||s form","Check the wire/frame handling that carried the signature for truncation or corruption","Convert raw (r||s) signatures to DER (or use a matching encoder) before calling these functions"],"exampleFix":"// before\nnormalized, err := p256.Normalize(raw64ByteSig) // raw r||s, not DER\n// after\nderSig := encodeRawToDER(raw64ByteSig) // wrap r and s in ASN.1 SEQUENCE\nnormalized, err := p256.Normalize(derSig)","handlingStrategy":"validation","validationCode":"if len(sig) < 8 || sig[0] != 0x30 {\n    return fmt.Errorf(\"signature is not DER-encoded ASN.1\")\n}","typeGuard":"func looksLikeDERSignature(b []byte) bool {\n    return len(b) >= 8 && b[0] == 0x30\n}","tryCatchPattern":"r, s, err := p256.parseSignature(sig) // via Normalize/IsNormalized/Swap\nif err != nil && err.Error() == \"invalid ASN.1\" {\n    // try raw r||s -> DER conversion before retrying\n}","preventionTips":["Agree on a single signature encoding (DER) across the protocol","Validate the leading 0x30 SEQUENCE tag on received signatures","Guard wire handling against truncation of signature fields"],"tags":["asn1","p256","signature","encoding"],"backgroundTag":"invalid-asn1-signature","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}