diff options
Diffstat (limited to 'core/src/main/java/org/spongycastle/pqc/asn1/RainbowPrivateKey.java')
-rw-r--r-- | core/src/main/java/org/spongycastle/pqc/asn1/RainbowPrivateKey.java | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/core/src/main/java/org/spongycastle/pqc/asn1/RainbowPrivateKey.java b/core/src/main/java/org/spongycastle/pqc/asn1/RainbowPrivateKey.java new file mode 100644 index 00000000..96648900 --- /dev/null +++ b/core/src/main/java/org/spongycastle/pqc/asn1/RainbowPrivateKey.java @@ -0,0 +1,349 @@ +package org.spongycastle.pqc.asn1; + +import org.spongycastle.asn1.ASN1EncodableVector; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.ASN1Object; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.ASN1OctetString; +import org.spongycastle.asn1.ASN1Primitive; +import org.spongycastle.asn1.ASN1Sequence; +import org.spongycastle.asn1.DEROctetString; +import org.spongycastle.asn1.DERSequence; +import org.spongycastle.pqc.crypto.rainbow.Layer; +import org.spongycastle.pqc.crypto.rainbow.util.RainbowUtil; + +/** + * Return the key data to encode in the PrivateKeyInfo structure. + * <p> + * The ASN.1 definition of the key structure is + * <pre> + * RainbowPrivateKey ::= SEQUENCE { + * CHOICE + * { + * oid OBJECT IDENTIFIER -- OID identifying the algorithm + * version INTEGER -- 0 + * } + * A1inv SEQUENCE OF OCTET STRING -- inversed matrix of L1 + * b1 OCTET STRING -- translation vector of L1 + * A2inv SEQUENCE OF OCTET STRING -- inversed matrix of L2 + * b2 OCTET STRING -- translation vector of L2 + * vi OCTET STRING -- num of elmts in each Set S + * layers SEQUENCE OF Layer -- layers of F + * } + * + * Layer ::= SEQUENCE OF Poly + * + * Poly ::= SEQUENCE { + * alpha SEQUENCE OF OCTET STRING + * beta SEQUENCE OF OCTET STRING + * gamma OCTET STRING + * eta INTEGER + * } + * </pre> + */ +public class RainbowPrivateKey + extends ASN1Object +{ + private ASN1Integer version; + private ASN1ObjectIdentifier oid; + + private byte[][] invA1; + private byte[] b1; + private byte[][] invA2; + private byte[] b2; + private byte[] vi; + private Layer[] layers; + + private RainbowPrivateKey(ASN1Sequence seq) + { + // <oidString> or version + if (seq.getObjectAt(0) instanceof ASN1Integer) + { + version = ASN1Integer.getInstance(seq.getObjectAt(0)); + } + else + { + oid = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0)); + } + + // <A1inv> + ASN1Sequence asnA1 = (ASN1Sequence)seq.getObjectAt(1); + invA1 = new byte[asnA1.size()][]; + for (int i = 0; i < asnA1.size(); i++) + { + invA1[i] = ((ASN1OctetString)asnA1.getObjectAt(i)).getOctets(); + } + + // <b1> + ASN1Sequence asnb1 = (ASN1Sequence)seq.getObjectAt(2); + b1 = ((ASN1OctetString)asnb1.getObjectAt(0)).getOctets(); + + // <A2inv> + ASN1Sequence asnA2 = (ASN1Sequence)seq.getObjectAt(3); + invA2 = new byte[asnA2.size()][]; + for (int j = 0; j < asnA2.size(); j++) + { + invA2[j] = ((ASN1OctetString)asnA2.getObjectAt(j)).getOctets(); + } + + // <b2> + ASN1Sequence asnb2 = (ASN1Sequence)seq.getObjectAt(4); + b2 = ((ASN1OctetString)asnb2.getObjectAt(0)).getOctets(); + + // <vi> + ASN1Sequence asnvi = (ASN1Sequence)seq.getObjectAt(5); + vi = ((ASN1OctetString)asnvi.getObjectAt(0)).getOctets(); + + // <layers> + ASN1Sequence asnLayers = (ASN1Sequence)seq.getObjectAt(6); + + byte[][][][] alphas = new byte[asnLayers.size()][][][]; + byte[][][][] betas = new byte[asnLayers.size()][][][]; + byte[][][] gammas = new byte[asnLayers.size()][][]; + byte[][] etas = new byte[asnLayers.size()][]; + // a layer: + for (int l = 0; l < asnLayers.size(); l++) + { + ASN1Sequence asnLayer = (ASN1Sequence)asnLayers.getObjectAt(l); + + // alphas (num of alpha-2d-array = oi) + ASN1Sequence alphas3d = (ASN1Sequence)asnLayer.getObjectAt(0); + alphas[l] = new byte[alphas3d.size()][][]; + for (int m = 0; m < alphas3d.size(); m++) + { + ASN1Sequence alphas2d = (ASN1Sequence)alphas3d.getObjectAt(m); + alphas[l][m] = new byte[alphas2d.size()][]; + for (int n = 0; n < alphas2d.size(); n++) + { + alphas[l][m][n] = ((ASN1OctetString)alphas2d.getObjectAt(n)).getOctets(); + } + } + + // betas .... + ASN1Sequence betas3d = (ASN1Sequence)asnLayer.getObjectAt(1); + betas[l] = new byte[betas3d.size()][][]; + for (int mb = 0; mb < betas3d.size(); mb++) + { + ASN1Sequence betas2d = (ASN1Sequence)betas3d.getObjectAt(mb); + betas[l][mb] = new byte[betas2d.size()][]; + for (int nb = 0; nb < betas2d.size(); nb++) + { + betas[l][mb][nb] = ((ASN1OctetString)betas2d.getObjectAt(nb)).getOctets(); + } + } + + // gammas ... + ASN1Sequence gammas2d = (ASN1Sequence)asnLayer.getObjectAt(2); + gammas[l] = new byte[gammas2d.size()][]; + for (int mg = 0; mg < gammas2d.size(); mg++) + { + gammas[l][mg] = ((ASN1OctetString)gammas2d.getObjectAt(mg)).getOctets(); + } + + // eta ... + etas[l] = ((ASN1OctetString)asnLayer.getObjectAt(3)).getOctets(); + } + + int numOfLayers = vi.length - 1; + this.layers = new Layer[numOfLayers]; + for (int i = 0; i < numOfLayers; i++) + { + Layer l = new Layer(vi[i], vi[i + 1], RainbowUtil.convertArray(alphas[i]), + RainbowUtil.convertArray(betas[i]), RainbowUtil.convertArray(gammas[i]), RainbowUtil.convertArray(etas[i])); + this.layers[i] = l; + + } + } + + public RainbowPrivateKey(short[][] invA1, short[] b1, short[][] invA2, + short[] b2, int[] vi, Layer[] layers) + { + this.version = new ASN1Integer(1); + this.invA1 = RainbowUtil.convertArray(invA1); + this.b1 = RainbowUtil.convertArray(b1); + this.invA2 = RainbowUtil.convertArray(invA2); + this.b2 = RainbowUtil.convertArray(b2); + this.vi = RainbowUtil.convertIntArray(vi); + this.layers = layers; + } + + public static RainbowPrivateKey getInstance(Object o) + { + if (o instanceof RainbowPrivateKey) + { + return (RainbowPrivateKey)o; + } + else if (o != null) + { + return new RainbowPrivateKey(ASN1Sequence.getInstance(o)); + } + + return null; + } + + public ASN1Integer getVersion() + { + return version; + } + + /** + * Getter for the inverse matrix of A1. + * + * @return the A1inv inverse + */ + public short[][] getInvA1() + { + return RainbowUtil.convertArray(invA1); + } + + /** + * Getter for the translation part of the private quadratic map L1. + * + * @return b1 the translation part of L1 + */ + public short[] getB1() + { + return RainbowUtil.convertArray(b1); + } + + /** + * Getter for the translation part of the private quadratic map L2. + * + * @return b2 the translation part of L2 + */ + public short[] getB2() + { + return RainbowUtil.convertArray(b2); + } + + /** + * Getter for the inverse matrix of A2 + * + * @return the A2inv + */ + public short[][] getInvA2() + { + return RainbowUtil.convertArray(invA2); + } + + /** + * Returns the layers contained in the private key + * + * @return layers + */ + public Layer[] getLayers() + { + return this.layers; + } + + /** + * Returns the array of vi-s + * + * @return the vi + */ + public int[] getVi() + { + return RainbowUtil.convertArraytoInt(vi); + } + + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + // encode <oidString> or version + if (version != null) + { + v.add(version); + } + else + { + v.add(oid); + } + + // encode <A1inv> + ASN1EncodableVector asnA1 = new ASN1EncodableVector(); + for (int i = 0; i < invA1.length; i++) + { + asnA1.add(new DEROctetString(invA1[i])); + } + v.add(new DERSequence(asnA1)); + + // encode <b1> + ASN1EncodableVector asnb1 = new ASN1EncodableVector(); + asnb1.add(new DEROctetString(b1)); + v.add(new DERSequence(asnb1)); + + // encode <A2inv> + ASN1EncodableVector asnA2 = new ASN1EncodableVector(); + for (int i = 0; i < invA2.length; i++) + { + asnA2.add(new DEROctetString(invA2[i])); + } + v.add(new DERSequence(asnA2)); + + // encode <b2> + ASN1EncodableVector asnb2 = new ASN1EncodableVector(); + asnb2.add(new DEROctetString(b2)); + v.add(new DERSequence(asnb2)); + + // encode <vi> + ASN1EncodableVector asnvi = new ASN1EncodableVector(); + asnvi.add(new DEROctetString(vi)); + v.add(new DERSequence(asnvi)); + + // encode <layers> + ASN1EncodableVector asnLayers = new ASN1EncodableVector(); + // a layer: + for (int l = 0; l < layers.length; l++) + { + ASN1EncodableVector aLayer = new ASN1EncodableVector(); + + // alphas (num of alpha-2d-array = oi) + byte[][][] alphas = RainbowUtil.convertArray(layers[l].getCoeffAlpha()); + ASN1EncodableVector alphas3d = new ASN1EncodableVector(); + for (int i = 0; i < alphas.length; i++) + { + ASN1EncodableVector alphas2d = new ASN1EncodableVector(); + for (int j = 0; j < alphas[i].length; j++) + { + alphas2d.add(new DEROctetString(alphas[i][j])); + } + alphas3d.add(new DERSequence(alphas2d)); + } + aLayer.add(new DERSequence(alphas3d)); + + // betas .... + byte[][][] betas = RainbowUtil.convertArray(layers[l].getCoeffBeta()); + ASN1EncodableVector betas3d = new ASN1EncodableVector(); + for (int i = 0; i < betas.length; i++) + { + ASN1EncodableVector betas2d = new ASN1EncodableVector(); + for (int j = 0; j < betas[i].length; j++) + { + betas2d.add(new DEROctetString(betas[i][j])); + } + betas3d.add(new DERSequence(betas2d)); + } + aLayer.add(new DERSequence(betas3d)); + + // gammas ... + byte[][] gammas = RainbowUtil.convertArray(layers[l].getCoeffGamma()); + ASN1EncodableVector asnG = new ASN1EncodableVector(); + for (int i = 0; i < gammas.length; i++) + { + asnG.add(new DEROctetString(gammas[i])); + } + aLayer.add(new DERSequence(asnG)); + + // eta + aLayer.add(new DEROctetString(RainbowUtil.convertArray(layers[l].getCoeffEta()))); + + // now, layer built up. add it! + asnLayers.add(new DERSequence(aLayer)); + } + + v.add(new DERSequence(asnLayers)); + + return new DERSequence(v); + } +} |