/*
*
* Copyright (c) 2013 - 2017 Lijun Liao
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License version 3
* as published by the Free Software Foundation with the addition of the
* following permission added to Section 15 as permitted in Section 7(a):
*
* FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
* THE AUTHOR LIJUN LIAO. LIJUN LIAO DISCLAIMS THE WARRANTY OF NON INFRINGEMENT
* OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License.
*
* You can be released from the requirements of the license by purchasing
* a commercial license. Buying such a license is mandatory as soon as you
* develop commercial activities involving the XiPKI software without
* disclosing the source code of your own applications.
*
* For more information, please contact Lijun Liao at this
* address: lijun.liao@gmail.com
*/
package org.xipki.pki.ca.client.shell.loadtest;
import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.RSAPublicKey;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Base64;
import org.xipki.commons.common.util.ParamUtil;
import org.xipki.commons.security.util.AlgorithmUtil;
import org.xipki.commons.security.util.KeyUtil;
/**
* @author Lijun Liao
* @since 2.0.0
*/
public abstract class KeyEntry {
// CHECKSTYLE:SKIP
public static final class RSAKeyEntry extends KeyEntry {
private static final String N_1024 =
"ALI9Q2yy0KKsfuJw6tOfXBY3aJevCKyCQYM4DWK0eL1noqh6Uk6Ro3AsLVcoJDlZ"
+ "xCOdqhwq41jsgrj5iEvf9tagNTnsLLscGEUkHWZDJIF9uQd5ISjFtcdaEGdv2v5K"
+ "f48Drcg7o+c+LtR5ZNmtaEySUtjRFYh3icMzoh6zzA/z";
private static final String N_2048 =
"AMQdbyhdRJvPE7WoyLBucRfELTPyMZZ3fEpIN+BiALpxfi2AAu4N9kvi/MT2xpfI"
+ "hdNHLDLX02tECy/XDdQiEKKJ2mfDr29me72yvO7PtpxUaPfyd6vzBEfGQqal42qZ"
+ "U1pmIgJm0jE4Gl4EdfyXEHsnekrLTjHiLnSr2WhlL+yY9xwO589VQIYziG53SbUM"
+ "cu0eMxzgfwT7UXKvPvbfzJjgWiin8PozENy+8yFzkCUOUK2uFa5iJPky8o5WSsqs"
+ "Q/nH7Jq0MyQaG58M+//0g3glXirbtX+BARGR130VeMAnxMktLc4VdZ+I75wNxLap"
+ "ksE19yQ4Ta0JRzGMwVZR7Pk=";
private static final String N_3072 =
"AL1F3ms6ImUDkIVEgjqM9NUQ2NpImvoNbvwq+zRLTvamIegsapwDi0cLkdD47vR9"
+ "bM50zuKX0+4FzJZe8MWQheTmSVbdF8EcORGh1OXYidmV9zFOrym961sBCvJ1x1W3"
+ "p00kyqi55gONxklvbK2MYAifoUIqe0L6TS4W0eJrWB25JuLP8U09xZQRFm1qAiSQ"
+ "JsZSfxcZfOtVOYp6oDsMqhk3RNKrpw/UqtfcRjYG+ZhccDZcmLS/UmHPHRuDsgCA"
+ "AebH3bDEqbQZ8hFqVdRDGWnIirLJ67+0e+3j6UjoI4ybSwy9O9g36rooC5bCboEA"
+ "46r03BiX28JMveHip689b+RAHgKy95Yd5eFIWYQBNAmUNZ+9hq4KTvrSb7ysge7d"
+ "qVY5nnsnmpXFyqy51dlem4npXAM73a9vLuEOioSOOqBwNDXyxBaETgqH4AWBdNK/"
+ "aSvwu2cUjFCKfds2Ycik+6pfu4gid2Pp5j2lXMvvtaIQNx88e2UTo8Jn+D+baFBX"
+ "uw==";
private static final String N_4096 =
"AMO03X0Vp9Diw8KW9zeuDSICAnohZT98o6lnJJR1pUZIPINOMuf/SG2vVR0Uv/cx"
+ "yY/8Fvn1ySzG0OjYE4mH9l1C4bvaiiKEMT1liX4WK2ndFFtwG3HmueRThn1uq2"
+ "y5WCUOZkD2/5atrcJfzWiox30zAikyLkOZ6kTY0anZ3UraF4Zj9Rvkpn4NMlUx"
+ "txN1CKrW+Cn1D2lPhGFRLB9joNOtlpt6zqv/Dyvfxc/6hnSQeQLd20bozbfKKs"
+ "Hvj+PU1wI2rHVI5XtS7efZCzvMzJ05wVZgTnQldxHbjw397u1uavsNncwmCcsH"
+ "crbvRWJDvvWvQWUOoG4KgMcGRbX0fdzMwntUMvO7A9AIlb4KtcPicpIQGYsiTe"
+ "WxM+Bpawo2a1ENy+HahP9rCU8i+bWRR8zsEhmuT6E7BK6/VmHU6NKbjkMIjIXN"
+ "GvULvVX6b1+hBOinVTm4ly+33ZK7zsl0nML5e0c7jFvq4XPvpi42kkP1RNjle0"
+ "zNIHdtWkRw/+lYpKmkuAU2gvu/iZXkvZBw9ncqABsRhbhfiwQlODOaF9h20rUW"
+ "HArzIk6vrsRyMjm5U9bKVimYaalQCmq1Uq49EYazIa31e5uDDMnbfcmMoPyi9Z"
+ "5jQAVfm+tWuvM+S118s3d/mCpoX62O3gLaHNpPpD8CHoOagGcqthk+9/wWarhR";
private static final BigInteger publicExponent = BigInteger.valueOf(65535);
private final SubjectPublicKeyInfo spki;
public RSAKeyEntry(final int keysize) throws Exception {
if (keysize % 1024 != 0) {
throw new IllegalArgumentException("invalid RSA keysize " + keysize);
}
AlgorithmIdentifier keyAlgId = new AlgorithmIdentifier(
PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE);
String modulusStr;
if (keysize == 1024 || keysize == 2048 || keysize == 3072 || keysize == 4096) {
if (keysize == 1024) {
modulusStr = N_1024;
} else if (keysize == 2048) {
modulusStr = N_2048;
} else if (keysize == 3072) {
modulusStr = N_3072;
} else { // if (keysize == 4096) {
modulusStr = N_4096;
}
BigInteger modulus = base64ToInt(modulusStr);
this.spki = new SubjectPublicKeyInfo(keyAlgId,
new org.bouncycastle.asn1.pkcs.RSAPublicKey(modulus, publicExponent));
} else {
KeyPairGenerator kp = KeyPairGenerator.getInstance("RSA");
kp.initialize(keysize);
RSAPublicKey publicKey = (RSAPublicKey) kp.generateKeyPair().getPublic();
this.spki = new SubjectPublicKeyInfo(keyAlgId,
new org.bouncycastle.asn1.pkcs.RSAPublicKey(
publicKey.getModulus(), publicKey.getPublicExponent()));
}
}
private static BigInteger base64ToInt(final String base64Str) {
return new BigInteger(1, Base64.decode(base64Str));
}
@Override
public SubjectPublicKeyInfo getSubjectPublicKeyInfo() {
return spki;
}
} // class RSAKeyEntry
// CHECKSTYLE:SKIP
public static final class DSAKeyEntry extends KeyEntry {
private static final String P_1024 =
"AM/6AjYLnnzRa99zmdhuMmikFKF/HhotHagBxoHlT4alq415sX94psaJPI3D5+/e"
+ "YUaZbnFMn/IEBh6YyEL4zPQs4xOYdcNoMJ6XccGelEHjVWDvocf00L417XiTJObM"
+ "UVHgFrkTPZ7G/mDBFMQ1WVrSSwnjPPDSCkIRiiGiCQqv";
private static final String Q_1024 =
"ANMDutPywwIBAbqpSxN8CAvbPkaL";
private static final String G_1024 =
"AcFvVWWRJlZsT2xCtto0gZj6QyaVAVJmvkZinCm2kafbFPQ+MLeZJKk3mvCaq2i8"
+ "DPptJ5LC1FaaE+Is4rhX0BcW5/rxxSk6JVboakH48KEg5nZvzphMNe9mC2bYV29z"
+ "BbyiYvs9v7EhAI7bKlvOaAb6XyB//fUh1+GYzP15HOw=";
private static final String Y_1024 =
"AMjz/ko+WVNXbLo7ixe+iIU2OpgngYIaSZQkbFFQ6E/ePlmgPlFY9gOV7CrjKYfn"
+ "MgU33SZHipa7Zo6LmgjNZ6VE2FE8PGE+CHM+XZMQlZdOtKZLMfRWUdYfUZ5D7j+1"
+ "3HlpW2ahfeClF5xuhwjcTDm7VdxZ+rVscp+QzF7Je35p";
private static final String P_2048 =
"ANAwGdtm8DJ6YHsC9A9c5bmg8saK4TShCmWoC0sLRwaueN/thcXQKjG4qNQu1BiR"
+ "wIGwlPqbX5F+i/kILuJ4xvcoffMsLZG9WoI8bG5Y+Ld9KWOJ/KDiYjdX5R9flbmq"
+ "gnMBUbscsLMStNBaHFZYe58S4uClVS6v7poi6s3e/B3ryvWPG4zIamFxV72DmSWo"
+ "nArfljTleJ/pVqlWW5WOTqXjk11ab53PSJGWPAyhfgZWhHTwsKt+HgemrA8D55us"
+ "vDVPhYNsnEy4FtJEbIJSsIKO4qGrhDA2mZeH30EXhZx83HWRML0GIP+tDguBN+hI"
+ "w7G9DpwQQL+f4lowf9rde38=";
private static final String Q_2048 =
"AO236rjUtJKK0CDLx+koJmwrX4xzffhW/hdqCOb8eOmV";
private static final String G_2048 =
"ALsVY3D6QRDnBiwfrbl4Br9wE5D9RZlPt6lUYmOIQFptcD1RWP0ZuajmDQ90FLJ/"
+ "jamGgqeIY+ZyA0UZqDcDtfrIB0sOML7xIqqUyTxV/UiIHnWVf9Xa9JGUWrUoqvVG"
+ "qiDI1G0OcIuBykDAHTUo0J54TKZP0DMILkwO0kqf+SM/mH4Q1qxV3RfRDUqc3v9s"
+ "/LgmshkkBsIapsh5AADA2GAoHnrLlgimgJS4zKoytCYYGtL0NqN4vyGiIQaeoOv4"
+ "JRwZ+gQsy7OA0nkDRWnAFsPOnPxQqsEGmfE8VGzXrHl42jcavPuJ1o3CCeMq30D0"
+ "VbEuwEMCUNBcjHTEpF0jnqs=";
private static final String Y_2048 =
"Pmn2UvUGcvhAwl57D86OPUdhiPJr4qaBNy9GAkUca4nkoQthP90dhvqB6b4FvJBr"
+ "jsWoPVQSxW+pX2vfbjscQMm4Kt5zaqeHnV/Rod4l5VeW7sqoRqBR7nzlke+xHkT0"
+ "wM3XkCp2E6BTAhT0qtp05w6onOoWIMv5Ydd04xwNB8lFF+A2uJrt3QlHXHvRW1no"
+ "Sf7bRDWC6JKLMRd+G0H8USMMT7UNUgen1lXbIH0q1GDph0z1MZkbUwewE/dG6KBL"
+ "3Km1hBmuWyUrqHLznKYPwhmcOqWpTGn2PJrmdEJdjhdhwpWT1POhiyP+YxxbFNv/"
+ "Kjkdw4wQAVloP0QZ4wH/IA==";
private static final String P_3072 =
"AOcper98q/F5dOpeZMTAxQiD3Sptsr0b19WMMwO+/P0YqjiS1LNqhX2ULuCv/oD1"
+ "TtgfRx5bNhsg4jA+mLtGHZAO2nGrF9fwlyxyv5gcx4D6WfDaLx1ZVGGcux8PlgLz"
+ "dshN10t6Icyl28Ky/G8HOFwu7kmHSw6fujsCqW0CvjiRW+sQ9N2Fuzjivg9axCyL"
+ "MtFLXUcQuIyHhlQWSQyrQkhAG0qLfLWpzM0BdWpL0hDSKgjOTNvYphRquqdzn90g"
+ "bXTwcQQdtuiQWg6WGhAz7feyuATmhESE2i2P5LV9LQGBG6j3zfU3ITmyexb4rFbp"
+ "gRSIWZ0nrs5uQ0lYZgUyr+dnzFnNqYZB7aNw5cFR5TWKcxTx0yp9kMMjjZSiQQc2"
+ "TVm254f6rztbERjU7HXxPFROujufBoTeBj0ayNxVJRIBs6XgSpE7/Gw3OJWJVMYT"
+ "5iA0MZv0Vs+WKdHoCKCZ8mfZbIisxCpFV8PW9/Xz6T59rBJxs51ZdwwyHz/EB7es"
+ "EQ==";
private static final String Q_3072 =
"ALQa/gl8UpkX42IsgfnihnQDS+NQ5US6eYGDz34guCib";
private static final String G_3072 =
"FyAOku6IrTU1iI6S0gl3soIF3mRbA/WiKpXu4ZCOdf9fHA12XtXPWRc7jaFBZucp"
+ "uxYtmDeUwCZRFX+HWpkptVv6LT8OIDbCFFfJlo6i0d1ulq9ybOLtcWXlqIcp4Z0v"
+ "LbFcxUr79CYp/mwdXzMwD+v7GFTa6feJdQENEfnwOGLUItOm+6OBcft+94xvDCmx"
+ "tfYYkgEaFvRFjVKy+9kDuf6OfFKM0RDX4tvvpPwpXdYghjk6C/9e0jqloW20DhsW"
+ "fBDmhp5cPSkjUDDSOz0JrOvT7MBeqefez6PbgMywZFiY+iBOZiIay2o5tI2uOaGq"
+ "z1K/1xo7tXMlZu0wFuxtwrThFbmbGIXAMCC4hNeW4hFKDRnYZtnRKChhh3gNx3eO"
+ "/58as/UIa8ApnjvG9tLpYtmlfJlgzlmEAuuB08qMg+T9tUjKQZWgEOiT6INFZS0P"
+ "mbSZgzJACYY6dMnywnne97TrgCccXuoTRV3derD91tU6lhfR5B4ZADXVClNrf7Nl";
private static final String Y_3072 =
"aiFUID1NF6SllNJf2RDMik1rU2A5VQc4pLw8wfvxG2WXCSTeuWnDB7b3HBtQOwox"
+ "lYaDQnKBEcly61aVbLKP+TD8dngJQNlr42M07u2drT2ADbk3cLWQ8lk27LBWjntX"
+ "oXduWz2onw1FEdh2nJSTkHZGBaQpUt8vwxB3IWoGsaazOKLnm/rZlK9g9Rs0RCXA"
+ "8KViQEUuAU1h/tt2bEFgOECQ6efm3oBeG3TfpstMud7QaGyyFnTgRxrZQpC1Et3D"
+ "e8TVvIy3uUjnOjGDVV8qGVjsI3J9zX3w5TbTDB4+lbMpc9/oMd26veU+8+7GY5Sz"
+ "iEPTcZF38POgm8I9Nxe5gxtiNJyOMQZC20rnffJljVLe8L1LrXPj0MJfVZMLXiyz"
+ "SLFRUj7ZpN4rzgQYkB0ETN40DFFk3a2gC9E2g+EdksAW0h+IAElikX4Q4Ja0kzXu"
+ "wJfVmq5g/Sp4ysk+JTzAl6r4T1dDr9BXpGgRdYdgwE/2RTMfunqTcUYlV752sbvy";
private SubjectPublicKeyInfo spki;
public DSAKeyEntry(final int plength) throws Exception {
if (plength == 1024) {
init(P_1024, Q_1024, G_1024, Y_1024);
} else if (plength == 2048) {
init(P_2048, Q_2048, G_2048, Y_2048);
} else if (plength == 3072) {
init(P_3072, Q_3072, G_3072, Y_3072);
} else {
if (plength % 1024 != 0) {
throw new IllegalArgumentException("invalid DSA pLength " + plength);
}
int qlength;
if (plength >= 2048) {
qlength = 256;
} else {
qlength = 160;
}
KeyPair kp = KeyUtil.generateDSAKeypair(plength, qlength, new SecureRandom());
DSAPublicKey pk = (DSAPublicKey) kp.getPublic();
init(pk.getParams().getP(), pk.getParams().getQ(), pk.getParams().getG(),
pk.getY());
}
}
// CHECKSTYLE:OFF
private void init(final String p, final String q, final String g, final String y)
throws IOException {
// CHECKSTYLE:ON
init(base64ToInt(p), base64ToInt(q), base64ToInt(g), base64ToInt(y));
}
private static BigInteger base64ToInt(final String base64Str) {
return new BigInteger(1, Base64.decode(base64Str));
}
// CHECKSTYLE:OFF
private void init(final BigInteger p, final BigInteger q, final BigInteger g,
final BigInteger y) throws IOException {
// CHECKSTYLE:ON
ASN1EncodableVector vec = new ASN1EncodableVector();
vec.add(new ASN1Integer(p));
vec.add(new ASN1Integer(q));
vec.add(new ASN1Integer(g));
ASN1Sequence dssParams = new DERSequence(vec);
AlgorithmIdentifier algId = new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa,
dssParams);
this.spki = new SubjectPublicKeyInfo(algId, new ASN1Integer(y));
}
@Override
public SubjectPublicKeyInfo getSubjectPublicKeyInfo() {
return spki;
}
} // class DSAKeyEntry
// CHECKSTYLE:SKIP
public static final class ECKeyEntry extends KeyEntry {
private final SubjectPublicKeyInfo spki;
public ECKeyEntry(final String curveNameOrOid) throws Exception {
ParamUtil.requireNonNull("curveNameOrOid", curveNameOrOid);
ASN1ObjectIdentifier curveOid = AlgorithmUtil.getCurveOidForCurveNameOrOid(
curveNameOrOid);
if (curveOid == null) {
throw new IllegalArgumentException("unknown curveNameOrOid '" + curveNameOrOid
+ "'");
}
String curveName = AlgorithmUtil.getCurveName(curveOid);
if (curveName == null) {
curveName = curveOid.getId();
}
AlgorithmIdentifier algId = new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey,
curveOid);
KeyPairGenerator kpgen = KeyPairGenerator.getInstance("ECDSA", "BC");
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(curveName);
kpgen.initialize(spec);
KeyPair kp = kpgen.generateKeyPair();
ECPoint baseQ = ((BCECPublicKey) kp.getPublic()).getQ();
spki = new SubjectPublicKeyInfo(algId, baseQ.getEncoded(false));
}
@Override
public SubjectPublicKeyInfo getSubjectPublicKeyInfo() {
return spki;
}
} // class ECKeyEntry
public abstract SubjectPublicKeyInfo getSubjectPublicKeyInfo();
}