peass-ng/PEASS-ng · error · Asn1Exception
unknown object encountered in constructed OCTET STRING:
Error message
unknown object encountered in constructed OCTET STRING:
What it means
BouncyCastle's Asn1InputStream.BuildObject, while parsing a constructed OCTET STRING, requires every child element to itself be an Asn1OctetString (segments to concatenate). If any child is a different ASN.1 type, it throws Asn1Exception, meaning the BER data violates the expected structure of a constructed OCTET STRING.
Source
Thrown at winPEAS/winPEASexe/winPEAS/3rdParty/BouncyCastle/asn1/Asn1InputStream.cs:112
if (isConstructed)
{
// TODO There are other tags that may be constructed (e.g. BitString)
switch (tagNo)
{
case Asn1Tags.OctetString:
{
//
// yes, people actually do this...
//
Asn1EncodableVector v = ReadVector(defIn);
Asn1OctetString[] strings = new Asn1OctetString[v.Count];
for (int i = 0; i != strings.Length; i++)
{
Asn1Encodable asn1Obj = v[i];
if (!(asn1Obj is Asn1OctetString))
{
throw new Asn1Exception("unknown object encountered in constructed OCTET STRING: "
+ Platform.GetTypeName(asn1Obj));
}
strings[i] = (Asn1OctetString)asn1Obj;
}
return new BerOctetString(strings);
}
case Asn1Tags.Sequence:
return CreateDerSequence(defIn);
case Asn1Tags.Set:
return CreateDerSet(defIn);
case Asn1Tags.External:
return new DerExternal(ReadVector(defIn));
default:
throw new IOException("unknown tag " + tagNo + " encountered");
}
}View on GitHub (pinned to 53fb989abc)
Solutions
- Validate the input bytes are genuine, well-formed DER/BER ASN.1 before parsing (e.g. with a strict DER parser or openssl asn1parse).
- Re-download or re-export the certificate/blob; the data is likely corrupt or truncated.
- If the sender legitimately nests other types, fix the encoder — constructed OCTET STRING children must be octet string segments per X.690.
- Catch Asn1Exception around ReadObject and handle malformed input gracefully.
Example fix
// before
Asn1Object obj = new Asn1InputStream(data).ReadObject();
// after
try { Asn1Object obj = new Asn1InputStream(data).ReadObject(); }
catch (Asn1Exception ex) { throw new InvalidDataException("Malformed ASN.1 OCTET STRING", ex); } Defensive patterns
Strategy: validation
Validate before calling
static bool LooksLikeAsn1OctetString(byte[] data)
{
if (data == null || data.Length < 2) return false;
byte tag = data[0];
// constructed OCTET STRING tags are 0x24 or 0x34
if (tag != 0x24 && tag != 0x34) return false;
// second byte should be a plausible definite length for small blobs
return (data[1] & 0x80) == 0 || data.Length > 2;
} Type guard
static bool IsAsn1OctetString(Asn1Encodable o) => o is Asn1OctetString;
Try / catch
Asn1Object obj;
try {
obj = new Asn1InputStream(data).ReadObject();
} catch (Asn1Exception ex) {
throw new InvalidDataException("Constructed OCTET STRING contains non-octet-string child: " + ex.Message, ex);
} Prevention
- Validate input with a strict DER linter (openssl asn1parse) before parsing
- Never parse raw downloads that might be HTML error pages — check content type/headers
- Re-export certificates from a trusted tool rather than hand-crafting ASN.1 bytes
- Catch Asn1Exception at parse boundaries and report which input file failed
When it happens
Trigger: Parsing DER/BER bytes where a constructed (0x24/0x34 tagged) OCTET STRING contains nested elements of other types (SEQUENCE, UTF8String, INTEGER, etc.) instead of octet string segments — i.e. malformed or non-conformant ASN.1 data.
Common situations: Feeding hand-crafted or corrupt certificate/PKCS blobs to the parser; a data source that is not actually ASN.1 (HTML error page, truncated download); BER data produced by a non-compliant encoder mixing types inside constructed octet strings.
Related errors
- unknown tag {tagNo} encountered
- unexpected end-of-contents marker
- indefinite-length primitive encoding encountered
- DER length more than 4 bytes:
- BOOLEAN value should have 1 byte in it
AI-assisted analysis of peass-ng/PEASS-ng@53fb989abc (2026-09-02).
Data as JSON: /api/errors/b56f687c4347f48e.
Report an issue: GitHub.