package model.csr; import annotations.Assoc; import model.asn1.ASN1Object; import model.asn1.Int; import model.asn1.Tag; import model.asn1.TagClass; import model.asn1.exceptions.ParseException; import model.asn1.parsing.BytesReader; import model.pki.SubjectPublicKeyInfo; import model.x501.Name; import java.util.Arrays; import java.util.Collection; import java.util.stream.Stream; /** * Represents a RFC2986 / PKCS#10 CSR CertificationRequestInfo object. * For more info on CRL, see {@link CertificationRequest}. * *
 *    DEFINITIONS IMPLICIT TAGS ::=
 *
 *    CertificationRequestInfo ::= SEQUENCE {
 *         version       INTEGER { v1(0) } (v1,...),
 *         subject       Name,
 *         subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
 *         attributes    [0] Attributes{{ CRIAttributes }}
 *    }
 *
 * 
*

* It represents all information of a CSR (version, subject, public key, attributes). * It will be signed, and the signature is in {@link CertificationRequest}. */ public class CertificationRequestInfo extends ASN1Object { public static final int VERSION_V1 = 0; /** * Version of the CRL. Always {@link CertificationRequestInfo#VERSION_V1} (0). */ @Assoc(partOf = true) private final Int version; /** * Subject of the requested certificate */ @Assoc(partOf = true) private final Name subject; /** * The public key to request. */ @Assoc(partOf = true) private final SubjectPublicKeyInfo subjectPKInfo; /** * The request attributes. */ @Assoc(partOf = true) private final Attributes attributes; /** * EFFECTS: Construct with the given version, subject, pubkey, attributes, and the given tags. * REQUIRES: Version must be {@link CertificationRequestInfo#VERSION_V1}. The fields must have correct tags as * described in class specification. */ public CertificationRequestInfo(Tag tag, Tag parentTag, final Int version, final Name subject, final SubjectPublicKeyInfo subjectPKInfo, final Attributes attributes) { super(tag, parentTag); this.version = version; this.subject = subject; this.subjectPKInfo = subjectPKInfo; this.attributes = attributes; } /** * EFFECTS: Parse the object with the given DER input. * Throws {@link ParseException} if the input is invalid: * - Any fields missing (version, subject, subjectPKInfo, attributes) * - Any fields having an incorrect tag (as seen in the ASN.1 definition) * - Any fields with encoding instructions that violate implicit / explicit encoding rules * - Other issues found during parsing the object, like early EOF (see {@link ASN1Object}) * MODIFIES: this, encoded */ public CertificationRequestInfo(BytesReader encoded, boolean hasParentTag) throws ParseException { super(encoded, hasParentTag); this.version = new Int(encoded, false); this.version.getTag().enforce(Int.TAG); if (this.version.getLong() != VERSION_V1) { throw new ParseException("Illegal version " + this.version.getLong()); } this.subject = new Name(encoded, false); this.subject.getTag().enforce(TAG_SEQUENCE); this.subjectPKInfo = new SubjectPublicKeyInfo(encoded, false); this.subjectPKInfo.getTag().enforce(TAG_SEQUENCE); this.attributes = new Attributes(encoded, false); this.attributes.getTag().enforce(new Tag(TagClass.CONTEXT_SPECIFIC, true, 0)); } /** * EFFECTS: Encode the value of that object, in the same order and format as denoted in the ASN.1 specification. */ @Override public Byte[] encodeValueDER() { return Stream.of(Arrays.asList(version.encodeDER()), Arrays.asList(subject.encodeDER()), Arrays.asList(subjectPKInfo.encodeDER()), Arrays.asList(attributes.encodeDER())) .flatMap(Collection::stream) .toArray(Byte[]::new); } public Int getVersion() { return version; } public Name getSubject() { return subject; } public SubjectPublicKeyInfo getSubjectPKInfo() { return subjectPKInfo; } public Attributes getAttributes() { return attributes; } }