| package org.bouncycastle.pqc.jcajce.provider.rainbow; |
| |
| import java.io.IOException; |
| import java.security.PrivateKey; |
| import java.util.Arrays; |
| |
| import org.bouncycastle.asn1.DERNull; |
| import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; |
| import org.bouncycastle.asn1.x509.AlgorithmIdentifier; |
| import org.bouncycastle.pqc.asn1.PQCObjectIdentifiers; |
| import org.bouncycastle.pqc.asn1.RainbowPrivateKey; |
| import org.bouncycastle.pqc.crypto.rainbow.Layer; |
| import org.bouncycastle.pqc.crypto.rainbow.RainbowPrivateKeyParameters; |
| import org.bouncycastle.pqc.crypto.rainbow.util.RainbowUtil; |
| import org.bouncycastle.pqc.jcajce.spec.RainbowPrivateKeySpec; |
| |
| /** |
| * The Private key in Rainbow consists of the linear affine maps L1, L2 and the |
| * map F, consisting of quadratic polynomials. In this implementation, we |
| * denote: L1 = A1*x + b1 L2 = A2*x + b2 |
| * <p> |
| * The coefficients of the polynomials in F are stored in 3-dimensional arrays |
| * per layer. The indices of these arrays denote the polynomial, and the |
| * variables. |
| * </p><p> |
| * More detailed information about the private key is to be found in the paper |
| * of Jintai Ding, Dieter Schmidt: Rainbow, a New Multivariable Polynomial |
| * Signature Scheme. ACNS 2005: 164-175 (http://dx.doi.org/10.1007/11496137_12) |
| * </p> |
| */ |
| public class BCRainbowPrivateKey |
| implements PrivateKey |
| { |
| private static final long serialVersionUID = 1L; |
| |
| // the inverse of L1 |
| private short[][] A1inv; |
| |
| // translation vector element of L1 |
| private short[] b1; |
| |
| // the inverse of L2 |
| private short[][] A2inv; |
| |
| // translation vector of L2 |
| private short[] b2; |
| |
| /* |
| * components of F |
| */ |
| private Layer[] layers; |
| |
| // set of vinegar vars per layer. |
| private int[] vi; |
| |
| |
| /** |
| * Constructor. |
| * |
| * @param A1inv |
| * @param b1 |
| * @param A2inv |
| * @param b2 |
| * @param layers |
| */ |
| public BCRainbowPrivateKey(short[][] A1inv, short[] b1, short[][] A2inv, |
| short[] b2, int[] vi, Layer[] layers) |
| { |
| this.A1inv = A1inv; |
| this.b1 = b1; |
| this.A2inv = A2inv; |
| this.b2 = b2; |
| this.vi = vi; |
| this.layers = layers; |
| } |
| |
| /** |
| * Constructor (used by the {@link RainbowKeyFactorySpi}). |
| * |
| * @param keySpec a {@link RainbowPrivateKeySpec} |
| */ |
| public BCRainbowPrivateKey(RainbowPrivateKeySpec keySpec) |
| { |
| this(keySpec.getInvA1(), keySpec.getB1(), keySpec.getInvA2(), keySpec |
| .getB2(), keySpec.getVi(), keySpec.getLayers()); |
| } |
| |
| public BCRainbowPrivateKey( |
| RainbowPrivateKeyParameters params) |
| { |
| this(params.getInvA1(), params.getB1(), params.getInvA2(), params.getB2(), params.getVi(), params.getLayers()); |
| } |
| |
| /** |
| * Getter for the inverse matrix of A1. |
| * |
| * @return the A1inv inverse |
| */ |
| public short[][] getInvA1() |
| { |
| return this.A1inv; |
| } |
| |
| /** |
| * Getter for the translation part of the private quadratic map L1. |
| * |
| * @return b1 the translation part of L1 |
| */ |
| public short[] getB1() |
| { |
| return this.b1; |
| } |
| |
| /** |
| * Getter for the translation part of the private quadratic map L2. |
| * |
| * @return b2 the translation part of L2 |
| */ |
| public short[] getB2() |
| { |
| return this.b2; |
| } |
| |
| /** |
| * Getter for the inverse matrix of A2 |
| * |
| * @return the A2inv |
| */ |
| public short[][] getInvA2() |
| { |
| return this.A2inv; |
| } |
| |
| /** |
| * 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 vi; |
| } |
| |
| /** |
| * Compare this Rainbow private key with another object. |
| * |
| * @param other the other object |
| * @return the result of the comparison |
| */ |
| public boolean equals(Object other) |
| { |
| if (other == null || !(other instanceof BCRainbowPrivateKey)) |
| { |
| return false; |
| } |
| BCRainbowPrivateKey otherKey = (BCRainbowPrivateKey)other; |
| |
| boolean eq = true; |
| // compare using shortcut rule ( && instead of &) |
| eq = eq && RainbowUtil.equals(A1inv, otherKey.getInvA1()); |
| eq = eq && RainbowUtil.equals(A2inv, otherKey.getInvA2()); |
| eq = eq && RainbowUtil.equals(b1, otherKey.getB1()); |
| eq = eq && RainbowUtil.equals(b2, otherKey.getB2()); |
| eq = eq && Arrays.equals(vi, otherKey.getVi()); |
| if (layers.length != otherKey.getLayers().length) |
| { |
| return false; |
| } |
| for (int i = layers.length - 1; i >= 0; i--) |
| { |
| eq &= layers[i].equals(otherKey.getLayers()[i]); |
| } |
| return eq; |
| } |
| |
| public int hashCode() |
| { |
| int hash = layers.length; |
| |
| hash = hash * 37 + org.bouncycastle.util.Arrays.hashCode(A1inv); |
| hash = hash * 37 + org.bouncycastle.util.Arrays.hashCode(b1); |
| hash = hash * 37 + org.bouncycastle.util.Arrays.hashCode(A2inv); |
| hash = hash * 37 + org.bouncycastle.util.Arrays.hashCode(b2); |
| hash = hash * 37 + org.bouncycastle.util.Arrays.hashCode(vi); |
| |
| for (int i = layers.length - 1; i >= 0; i--) |
| { |
| hash = hash * 37 + layers[i].hashCode(); |
| } |
| |
| |
| return hash; |
| } |
| |
| /** |
| * @return name of the algorithm - "Rainbow" |
| */ |
| public final String getAlgorithm() |
| { |
| return "Rainbow"; |
| } |
| |
| public byte[] getEncoded() |
| { |
| RainbowPrivateKey privateKey = new RainbowPrivateKey(A1inv, b1, A2inv, b2, vi, layers); |
| |
| PrivateKeyInfo pki; |
| try |
| { |
| AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PQCObjectIdentifiers.rainbow, DERNull.INSTANCE); |
| pki = new PrivateKeyInfo(algorithmIdentifier, privateKey); |
| } |
| catch (IOException e) |
| { |
| e.printStackTrace(); |
| return null; |
| } |
| try |
| { |
| byte[] encoded = pki.getEncoded(); |
| return encoded; |
| } |
| catch (IOException e) |
| { |
| e.printStackTrace(); |
| return null; |
| } |
| } |
| |
| public String getFormat() |
| { |
| return "PKCS#8"; |
| } |
| } |