package model.pki; import annotations.Assoc; import model.asn1.ASN1Object; import model.asn1.BitString; import model.asn1.Tag; import model.asn1.exceptions.ParseException; import model.asn1.parsing.BytesReader; import java.util.Arrays; import java.util.Collection; import java.util.stream.Stream; /** * Represents the following ASN.1 structure: *
 *     SubjectPublicKeyInfo ::= SEQUENCE {
 *          algorithm AlgorithmIdentifier{{SupportedAlgorithms}},
 *          subjectPublicKey BIT STRING,
 *     ... }
 * 
* It represents the public key of a subject, in a certificate. */ public class SubjectPublicKeyInfo extends ASN1Object { /** * The algorithm used. */ @Assoc(partOf = true) private final AlgorithmIdentifier algorithm; /** * The public key. */ @Assoc(partOf = true) private final BitString subjectPublicKey; /** * EFFECTS: Init with tags, algorithm, subjectPublicKey. For tags, see {@link ASN1Object}. * REQUIRES: The public key should be a valid $algorithm key. Algorithm and publicKey should have default UNIVERSAL * tags (SEQUENCE and BIT STRING). */ public SubjectPublicKeyInfo(Tag tag, Tag parentTag, final AlgorithmIdentifier algorithm, final BitString subjectPublicKey) { super(tag, parentTag); this.algorithm = algorithm; this.subjectPublicKey = subjectPublicKey; } /** * EFFECTS: Parse input DER. * Throws {@link ASN1Object} if invalid: * - Any fields missing (info, algorithm, signature) * - 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 SubjectPublicKeyInfo(BytesReader encoded, boolean hasParentTag) throws ParseException { super(encoded, hasParentTag); this.algorithm = new AlgorithmIdentifier(encoded, false); this.algorithm.getTag().enforce(TAG_SEQUENCE); this.subjectPublicKey = new BitString(encoded, false); this.subjectPublicKey.getTag().enforce(BitString.TAG); } /** * EFFECTS: Encode the fields into DER, in the order. */ @Override public Byte[] encodeValueDER() { return Stream.of(Arrays.asList(algorithm.encodeDER()), Arrays.asList(subjectPublicKey.encodeDER())) .flatMap(Collection::stream) .toArray(Byte[]::new); } public AlgorithmIdentifier getAlgorithm() { return algorithm; } public BitString getSubjectPublicKey() { return subjectPublicKey; } }