package org.bouncycastle.pqc.asn1; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1Object; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.pqc.crypto.rainbow.util.RainbowUtil; /** * This class implements an ASN.1 encoded Rainbow public key. The ASN.1 definition * of this structure is: * <p/> * <pre> * RainbowPublicKey ::= SEQUENCE { * CHOICE * { * oid OBJECT IDENTIFIER -- OID identifying the algorithm * version INTEGER -- 0 * } * docLength Integer -- length of the code * coeffquadratic SEQUENCE OF OCTET STRING -- quadratic (mixed) coefficients * coeffsingular SEQUENCE OF OCTET STRING -- singular coefficients * coeffscalar SEQUENCE OF OCTET STRING -- scalar coefficients * } * </pre> */ public class RainbowPublicKey extends ASN1Object { private ASN1Integer version; private ASN1ObjectIdentifier oid; private ASN1Integer docLength; private byte[][] coeffQuadratic; private byte[][] coeffSingular; private byte[] coeffScalar; private RainbowPublicKey(ASN1Sequence seq) { // <oidString> or version if (seq.getObjectAt(0) instanceof ASN1Integer) { version = ASN1Integer.getInstance(seq.getObjectAt(0)); } else { oid = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0)); } docLength = ASN1Integer.getInstance(seq.getObjectAt(1)); ASN1Sequence asnCoeffQuad = ASN1Sequence.getInstance(seq.getObjectAt(2)); coeffQuadratic = new byte[asnCoeffQuad.size()][]; for (int quadSize = 0; quadSize < asnCoeffQuad.size(); quadSize++) { coeffQuadratic[quadSize] = ASN1OctetString.getInstance(asnCoeffQuad.getObjectAt(quadSize)).getOctets(); } ASN1Sequence asnCoeffSing = (ASN1Sequence)seq.getObjectAt(3); coeffSingular = new byte[asnCoeffSing.size()][]; for (int singSize = 0; singSize < asnCoeffSing.size(); singSize++) { coeffSingular[singSize] = ASN1OctetString.getInstance(asnCoeffSing.getObjectAt(singSize)).getOctets(); } ASN1Sequence asnCoeffScalar = (ASN1Sequence)seq.getObjectAt(4); coeffScalar = ASN1OctetString.getInstance(asnCoeffScalar.getObjectAt(0)).getOctets(); } public RainbowPublicKey(int docLength, short[][] coeffQuadratic, short[][] coeffSingular, short[] coeffScalar) { this.version = new ASN1Integer(0); this.docLength = new ASN1Integer(docLength); this.coeffQuadratic = RainbowUtil.convertArray(coeffQuadratic); this.coeffSingular = RainbowUtil.convertArray(coeffSingular); this.coeffScalar = RainbowUtil.convertArray(coeffScalar); } public static RainbowPublicKey getInstance(Object o) { if (o instanceof RainbowPublicKey) { return (RainbowPublicKey)o; } else if (o != null) { return new RainbowPublicKey(ASN1Sequence.getInstance(o)); } return null; } public ASN1Integer getVersion() { return version; } /** * @return the docLength */ public int getDocLength() { return this.docLength.getValue().intValue(); } /** * @return the coeffquadratic */ public short[][] getCoeffQuadratic() { return RainbowUtil.convertArray(coeffQuadratic); } /** * @return the coeffsingular */ public short[][] getCoeffSingular() { return RainbowUtil.convertArray(coeffSingular); } /** * @return the coeffscalar */ public short[] getCoeffScalar() { return RainbowUtil.convertArray(coeffScalar); } public ASN1Primitive toASN1Primitive() { ASN1EncodableVector v = new ASN1EncodableVector(); // encode <oidString> or version if (version != null) { v.add(version); } else { v.add(oid); } // encode <docLength> v.add(docLength); // encode <coeffQuadratic> ASN1EncodableVector asnCoeffQuad = new ASN1EncodableVector(); for (int i = 0; i < coeffQuadratic.length; i++) { asnCoeffQuad.add(new DEROctetString(coeffQuadratic[i])); } v.add(new DERSequence(asnCoeffQuad)); // encode <coeffSingular> ASN1EncodableVector asnCoeffSing = new ASN1EncodableVector(); for (int i = 0; i < coeffSingular.length; i++) { asnCoeffSing.add(new DEROctetString(coeffSingular[i])); } v.add(new DERSequence(asnCoeffSing)); // encode <coeffScalar> ASN1EncodableVector asnCoeffScalar = new ASN1EncodableVector(); asnCoeffScalar.add(new DEROctetString(coeffScalar)); v.add(new DERSequence(asnCoeffScalar)); return new DERSequence(v); } }