dorkbox.util.crypto.CryptoRSA Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of Utilities Show documentation
Show all versions of Utilities Show documentation
Utilities for use within Java projects
/*
* Copyright 2010 dorkbox, llc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dorkbox.util.crypto;
import org.bouncycastle.crypto.AsymmetricBlockCipher;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.bouncycastle.crypto.signers.PSSSigner;
import org.slf4j.Logger;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.SecureRandom;
/**
* This is here just for keeping track of how this is done. This should NOT be used, and instead use ECC crypto.
*/
@Deprecated
public final
class CryptoRSA {
public static
AsymmetricCipherKeyPair generateKeyPair(SecureRandom secureRandom, int keyLength) {
RSAKeyPairGenerator keyGen = new RSAKeyPairGenerator();
RSAKeyGenerationParameters params = new RSAKeyGenerationParameters(new BigInteger("65537"), // public exponent
secureRandom, //pnrg
keyLength, // key length
8); //the number of iterations of the Miller-Rabin primality test.
keyGen.init(params);
return keyGen.generateKeyPair();
}
/**
* RSA encrypt using public key A, and sign data with private key B.
*
* byte[0][] = encrypted data byte[1][] = signature
*
* @param logger
* may be null, if no log output is necessary
*
* @return empty byte[][] if error
*/
public static
byte[][] encryptAndSign(AsymmetricBlockCipher rsaEngine,
Digest digest,
RSAKeyParameters rsaPublicKeyA,
RSAPrivateCrtKeyParameters rsaPrivateKeyB,
byte[] bytes,
Logger logger) {
if (bytes.length == 0) {
return new byte[0][0];
}
byte[] encryptBytes = encrypt(rsaEngine, rsaPublicKeyA, bytes, logger);
if (encryptBytes.length == 0) {
return new byte[0][0];
}
// now sign it.
PSSSigner signer = new PSSSigner(rsaEngine, digest, digest.getDigestSize());
byte[] signatureRSA = CryptoRSA.sign(signer, rsaPrivateKeyB, encryptBytes, logger);
if (signatureRSA.length == 0) {
return new byte[0][0];
}
byte[][] total = new byte[2][];
total[0] = encryptBytes;
total[1] = signatureRSA;
return total;
}
/**
* RSA verify data with public key B, and decrypt using private key A.
*
* @param logger
* may be null, if no log output is necessary
*
* @return empty byte[] if error
*/
public static
byte[] decryptAndVerify(AsymmetricBlockCipher rsaEngine,
Digest digest,
RSAKeyParameters rsaPublicKeyA,
RSAPrivateCrtKeyParameters rsaPrivateKeyB,
byte[] encryptedData,
byte[] signature,
Logger logger) {
if (encryptedData.length == 0 || signature.length == 0) {
return new byte[0];
}
// verify encrypted data.
PSSSigner signer = new PSSSigner(rsaEngine, digest, digest.getDigestSize());
boolean verify = verify(signer, rsaPublicKeyA, signature, encryptedData);
if (!verify) {
return new byte[0];
}
return decrypt(rsaEngine, rsaPrivateKeyB, encryptedData, logger);
}
/**
* RSA encrypts data with a specified key.
*
* @param logger
* may be null, if no log output is necessary
*
* @return empty byte[] if error
*/
public static
byte[] encrypt(AsymmetricBlockCipher rsaEngine, RSAKeyParameters rsaPublicKey, byte[] bytes, Logger logger) {
rsaEngine.init(true, rsaPublicKey);
try {
int inputBlockSize = rsaEngine.getInputBlockSize();
if (inputBlockSize < bytes.length) {
int outSize = rsaEngine.getOutputBlockSize();
//noinspection NumericCastThatLosesPrecision
int realsize = (int) Math.round(bytes.length / (outSize * 1.0D) + 0.5);
ByteBuffer buffer = ByteBuffer.allocateDirect(outSize * realsize);
int position = 0;
while (position < bytes.length) {
int size = Math.min(inputBlockSize, bytes.length - position);
byte[] block = rsaEngine.processBlock(bytes, position, size);
buffer.put(block, 0, block.length);
position += size;
}
return buffer.array();
}
else {
return rsaEngine.processBlock(bytes, 0, bytes.length);
}
} catch (Exception e) {
if (logger != null) {
logger.error("Unable to perform RSA cipher.", e);
}
return new byte[0];
}
}
/**
* RSA decrypt data with a specified key.
*
* @param logger
* may be null, if no log output is necessary
*
* @return empty byte[] if error
*/
public static
byte[] decrypt(AsymmetricBlockCipher rsaEngine, RSAPrivateCrtKeyParameters rsaPrivateKey, byte[] bytes, Logger logger) {
rsaEngine.init(false, rsaPrivateKey);
try {
int inputBlockSize = rsaEngine.getInputBlockSize();
if (inputBlockSize < bytes.length) {
int outSize = rsaEngine.getOutputBlockSize();
//noinspection NumericCastThatLosesPrecision
int realsize = (int) Math.round(bytes.length / (outSize * 1.0D) + 0.5);
ByteArrayOutputStream buffer = new ByteArrayOutputStream(outSize * realsize);
int position = 0;
while (position < bytes.length) {
int size = Math.min(inputBlockSize, bytes.length - position);
byte[] block = rsaEngine.processBlock(bytes, position, size);
buffer.write(block, 0, block.length);
position += size;
}
return buffer.toByteArray();
}
else {
return rsaEngine.processBlock(bytes, 0, bytes.length);
}
} catch (Exception e) {
if (logger != null) {
logger.error("Unable to perform RSA cipher.", e);
}
return new byte[0];
}
}
/**
* RSA sign data with a specified key.
*
* @param logger
* may be null, if no log output is necessary
*
* @return empty byte[] if error
*/
public static
byte[] sign(PSSSigner signer, RSAPrivateCrtKeyParameters rsaPrivateKey, byte[] mesg, Logger logger) {
signer.init(true, rsaPrivateKey);
signer.update(mesg, 0, mesg.length);
try {
return signer.generateSignature();
} catch (Exception e) {
if (logger != null) {
logger.error("Unable to perform RSA cipher.", e);
}
return new byte[0];
}
}
/**
* RSA verify data with a specified key.
*/
public static
boolean verify(PSSSigner signer, RSAKeyParameters rsaPublicKey, byte[] sig, byte[] mesg) {
signer.init(false, rsaPublicKey);
signer.update(mesg, 0, mesg.length);
return signer.verifySignature(sig);
}
@SuppressWarnings("RedundantIfStatement")
public static
boolean compare(RSAKeyParameters publicA, RSAKeyParameters publicB) {
if (!publicA.getExponent()
.equals(publicB.getExponent())) {
return false;
}
if (!publicA.getModulus()
.equals(publicB.getModulus())) {
return false;
}
return true;
}
@SuppressWarnings("RedundantIfStatement")
public static
boolean compare(RSAPrivateCrtKeyParameters private1, RSAPrivateCrtKeyParameters private2) {
if (!private1.getModulus()
.equals(private2.getModulus())) {
return false;
}
if (!private1.getExponent()
.equals(private2.getExponent())) {
return false;
}
if (!private1.getDP()
.equals(private2.getDP())) {
return false;
}
if (!private1.getDQ()
.equals(private2.getDQ())) {
return false;
}
if (!private1.getP()
.equals(private2.getP())) {
return false;
}
if (!private1.getPublicExponent()
.equals(private2.getPublicExponent())) {
return false;
}
if (!private1.getQ()
.equals(private2.getQ())) {
return false;
}
if (!private1.getQInv()
.equals(private2.getQInv())) {
return false;
}
return true;
}
private
CryptoRSA() {
}
}