# Encode ASN.1 PKCS#8 Private Key with Public Key and attributes

I'm trying to encode an Ed25519 private key as a PEM file based on this document https://tools.ietf.org/html/rfc8410#page-7 .

I'm using an ASN.1 encoder written in Dart, and I can encode the private key without its public key and attributes as in this example:

-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEINTuctv5E1hK1bbY8fdp+K06/nwoy/HU++CXqI9EdVhC
-----END PRIVATE KEY-----


But I can't make sense of the specification on how to encode the public key and attributes like this one:

-----BEGIN PRIVATE KEY-----
MHICAQEwBQYDK2VwBCIEINTuctv5E1hK1bbY8fdp+K06/nwoy/HU++CXqI9EdVhC
oB8wHQYKKoZIhvcNAQkJFDEPDA1DdXJkbGUgQ2hhaXJzgSEAGb9ECWmEzf6FQbrB
Z9w7lshQhqowtrbLDFw4rXAxZuE=
-----END PRIVATE KEY------


Using the lapo.it ASN.1 decoder you can see the optional fields, but I can't recreate it. What does the 0 and 1 mean? And why it doesn't have the annotated type?

This is more about representation and manipulation of data in a computer program than cryptography. Questions about Dart or the use of libraries in Dart, are better asked on Stackoverflow.

The [0] and [1] are context-specific tags; more exactly they are tags that are not universal (because then the number-type mapping would be fixed and known) with a class that is not specified and thus defaults to context-specific.

Because they are IMPLICIT, the top-level ASN.1 type of their contents is not encoded, and cannot be shown by a generic decoder like the one you link -- see a page earlier, above the table of universal types.

[0] is Attributes which in rfc5958 (and many other places) is SET OF Attribute (with infoset constraint) where CMS-style Attribute is SEQUENCE { attrType OBJECT IDENTIFIER, attrValue SET OF ANY --DEFINED BY type-- } in the old ASN.1 notation, or with attrValue defined by an infoset in the new notation. Thus the decode of [0] shows the one SEQUENCE of OID plus SET containing UTF8STRING.

On the other hand, [1] is PublicKey ::= BIT STRING which has no internal structure, so it is shown as raw data -- including the prefixed value octet for unused_bits = 00, so the real value of the publickey is the remaining 32 octets.