AES Encryption and decryption using jks file - aes

I have one small doubt as i am new to AES.
I encrypted a string using one certificate with some password lets say , 'xxx'.
Now i duplicated the certificate by changing the password of it.
When i try to decrypt the encrypted string with the duplicated cert, it says Bad padding exception.Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
However, when i use the original cert, it decrypts properly.
Could anyone please guide me on it?
public SecretKey retrieveKey(String password, byte[] certFile) throws Exception {
try {
String alias = null;
certPass = password;
char[] pass = certPass.toCharArray();
KeyStore keyStore = KeyStore.getInstance("jceks");
InputStream inputStream = new ByteArrayInputStream(certFile);
keyStore.load(inputStream, pass);
Enumeration enumeration = keyStore.aliases();
while (enumeration.hasMoreElements()) {
alias = (String) enumeration.nextElement();
}
Certificate cert = keyStore.getCertificate(alias);
Key key = cert.getPublicKey();
aesSecretKey = new SecretKeySpec(key.getEncoded(), algorithm);
byte[] encoded = aesSecretKey.getEncoded();
byte[] encryptionKey = Arrays.copyOfRange(encoded, encoded.length - 16, encoded.length);
aesSecretKey = new SecretKeySpec(encryptionKey, algorithm);
} catch (IOException e) {
throw e;
} catch (Exception e) {
throw e;
}
return aesSecretKey;
}

You should use RSA to wrap / unwrap the AES key. The public key is not identical to the AES key, so the following code is certainly incorrect:
Key key = cert.getPublicKey();
aesSecretKey = new SecretKeySpec(key.getEncoded(), algorithm);

Related

How to convert encrypt java code below in flutter

I m requirement is to convert below java encrypt code to flutter as i need to encrypt few fields value before sending to api.
Below is java encrypt code which i need to convert to java
public static String encrypt(String text, String algo, Key key) {
byte[] cipherText;
String output;
try {
if("RSA".equals(algo)) {
throw new IllegalArgumentException("Do not pass just algo pass with padding and blocking stuff!");
}
if(BuildConfig.DEBUG) {
Log.d(TAG, "encrypt in: "+text);
Log.d(TAG, "algo: "+algo);
Log.d(TAG, "key: "+key);
}
final Cipher cipher = Cipher.getInstance(algo);
if(algo.contains("AES")) {
AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
} else {
cipher.init(Cipher.ENCRYPT_MODE, key);
}
cipherText = cipher.doFinal(text.getBytes(StandardCharsets.UTF_8));
output = new String(Base64.encode(cipherText));
if(BuildConfig.DEBUG) {
Log.d(TAG, "encrypt out: "+output);
}
return output;
} catch (Exception e) {
Log.e(TAG, SDKConstants.STRING_ERROR + e, e);
return null;
}
}
char[] encPwd = Objects.requireNonNull(CryptoHelper.encrypt(Objects.requireNonNull(binding.textIPassword.getEditText()).getText().toString(), CryptoHelper.ALGO_FOR_RSA, key)).toCharArray();
Please help me in converting above java code to flutter as i need to encrypt one field before sending it to api call.
Any help is appreciated!
Just work through the Java line by line and figure out Dart equivalents. Use the other linked question as your guide. This should work (if I guessed the cipher correctly):
import 'package:pointycastle/export.dart';
String encrypt(String plainText, RSAPublicKey public) {
final plainBytes = utf8.encode(plainText) as Uint8List;
final cipher = PKCS1Encoding(RSAEngine())
..init(true, PublicKeyParameter<RSAPublicKey>(public));
final cipherBytes = cipher.process(plainBytes);
return base64Encode(cipherBytes);
}

keyStore.getKey() returns NULL

I want to sign a PDF with a self generated certificate. In this process I need a keystore and private key. The signing will be made with PDFBox by using the class CreateSignature()
To generate a keyStore with a self generated certificate I am using this:
public KeyStore generateSampleKeyStoreWith509Certificate() throws KeyStoreException, NoSuchAlgorithmException,
CertificateException, IOException, UnrecoverableEntryException {
X509Certificate cert;
PrivateKey caKey;
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC");
keyPairGenerator.initialize(1024, new SecureRandom());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
caKey = keyPair.getPrivate();
Date notBefore = new Date();
Date notAfter = new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 365);
SubjectPublicKeyInfo spkInfo = SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded());
X509v3CertificateBuilder newGen = new X509v3CertificateBuilder(new X500Name(issuer), serial, notBefore,
notAfter, new X500Name(subject), spkInfo);
ContentSigner sigGen = new JcaContentSignerBuilder("SHA256WithRSAEncryption").setProvider("BC")
.build(caKey);
X509CertificateHolder certHolder = newGen.build(sigGen);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream is1 = new ByteArrayInputStream(certHolder.getEncoded());
cert = (X509Certificate) cf.generateCertificate(is1);
is1.close();
} catch (OperatorCreationException | CertificateException | IOException | NoSuchProviderException
| NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, password);
keyStore.setCertificateEntry("SelfSigned", cert);
return keyStore;
}
The certificate is entered correctly, but shouldn't there be a key, too? Or am I wrong that the keystore should be holding a key?
I'm just figuring this sibject, so I'm thankful of every bit of help.
X509Certificate[] certChain = new X509Certificate[1];
certChain[0] = cert;
keyStore.setKeyEntry("SelfSigned",caKey, password, certChain);
Adding the above code, at the bottom, enters the privateKey previously created to the keystore. It seems most examples on the internet assume loading a keystore with privatekey already entered before.

Hi! can anyone tell me how to validate the sha2+salt password while log in?

can anyone tell me how to validate the sha2+salt password while log in?? i am working in wicket framework and pg admin database, i was told to use hashing algorithm to create secure passwords. I just saw this example source code and i implemented it in my applciation and it just worked, but i dont know how to validate the salt+hash passwords while log in again. But i could able to validate the simple sha-2 paswwords but i couldn't and i don't know how to validate the sha2+salt password.
public class SHAExample {
public static void main(String[] args) throws NoSuchAlgorithmException {
String passwordToHash = "password";
String salt = getSalt();
String securePassword = get_SHA_1_SecurePassword(passwordToHash, salt);
System.out.println(securePassword);
securePassword = get_SHA_256_SecurePassword(passwordToHash, salt);
System.out.println(securePassword);
securePassword = get_SHA_384_SecurePassword(passwordToHash, salt);
System.out.println(securePassword);
securePassword = get_SHA_512_SecurePassword(passwordToHash, salt);
System.out.println(securePassword);
}
private static String get_SHA_1_SecurePassword(String passwordToHash, String salt)
{
String generatedPassword = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(salt.getBytes());
byte[] bytes = md.digest(passwordToHash.getBytes());
StringBuilder sb = new StringBuilder();
for(int i=0; i< bytes.length ;i++)
{
sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
}
generatedPassword = sb.toString();
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
return generatedPassword;
}
//Add salt
private static String getSalt() throws NoSuchAlgorithmException
{
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
byte[] salt = new byte[16];
sr.nextBytes(salt);
return salt.toString();
}
}
Output:
e4c53afeaa7a08b1f27022abd443688c37981bc4
You have to do the same steps as you did when storing the password hash. That means you calculate the hash of the entered password with the same algorithm and the same salt you used before, then you can compare the hashes.
Be aware that the SHA* hash algorithms are not secure to hash passwords, because they are ways too fast and can be brute-forced too easily. Instead you switch to a slow key-derivation function like BCrypt or PBKDF2.

Storing certificates in pkcs11 keystore

I am generating an RSA keypair in pkcs11 keystore, it was storing into smartcard and i am generating pkcs10 request. when i download the equivalent certificate how can i store it into smartcard(without privatekey since the key is already stored into smartcard) since i dont have access to the private key in the pkcs11 keystore.
String wdtokenpath = "path to dll file";
String pkcs11ConfigSettings = "name = SmartCard\n" + "library =" + wdtokenpath;
byte[] pkcs11ConfigBytes = pkcs11ConfigSettings.getBytes();
ByteArrayInputStream confStream = new ByteArrayInputStream(pkcs11ConfigBytes);
Provider pkcs11Provider = null;
Class sunPkcs11Class = Class.forName("sun.security.pkcs11.SunPKCS11");
Constructor pkcs11Constr = sunPkcs11Class.getConstructor(
java.io.InputStream.class);
pkcs11Provider = (Provider) pkcs11Constr.newInstance(confStream);
CallbackHandler call = new TextCallbackHandler();
Subject token = new Subject();
AuthProvider aprov = (AuthProvider) pkcs11Provider;
aprov.login(token, call);
System.out.println("Login successfully");
KeyPairGenerator keyGen1 = KeyPairGenerator.getInstance("RSA", aprov);
keyGen1.initialize(2048);
KeyPair pair1 = keyGen1.generateKeyPair();
PublicKey publicKey1 = pair1.getPublic();
String sigAlg = "SHA1withRSA";
PKCS10 pkcs10 = new PKCS10(publicKey1);
Signature signature = Signature.getInstance("SHA1withRSA", pkcs11Provider);
signature.initSign(pair1.getPrivate());
It depends on what kind of smart card you have, or what kind of PKCS#11 device you have. The implementation may differ.
When you are using SunPKCS11, you can do it like this:
public boolean uploadCertificate(X509Certificate cert, String label, String id) {
CK_ATTRIBUTE[] certificate = new CK_ATTRIBUTE[9];
certificate[0] = new CK_ATTRIBUTE(PKCS11Constants.CKA_CLASS, PKCS11Constants.CKO_CERTIFICATE);
certificate[1] = new CK_ATTRIBUTE(PKCS11Constants.CKA_TOKEN, true);
certificate[2] = new CK_ATTRIBUTE(PKCS11Constants.CKA_PRIVATE, false);
certificate[3] = new CK_ATTRIBUTE(PKCS11Constants.CKA_LABEL, label.toCharArray());
certificate[4] = new CK_ATTRIBUTE(PKCS11Constants.CKA_SUBJECT, cert.getSubjectX500Principal().getEncoded());
certificate[5] = new CK_ATTRIBUTE(PKCS11Constants.CKA_ID, HexUtils.hexStringToByteArray(id));
certificate[6] = new CK_ATTRIBUTE(PKCS11Constants.CKA_ISSUER, cert.getIssuerX500Principal().getEncoded());
certificate[7] = new CK_ATTRIBUTE(PKCS11Constants.CKA_SERIAL_NUMBER, cert.getSerialNumber().toByteArray());
try {
certificate[8] = new CK_ATTRIBUTE(PKCS11Constants.CKA_VALUE, cert.getEncoded());
p11.C_CreateObject(hSession, certificate);
} catch (Exception e) {
logger.log(Level.SEVERE, "Upload Certificate Exception", e);
return false;
}
return true;
}
Or with IAIK PKCS#11 Wrapper:
// create certificate object template
X509PublicKeyCertificate pkcs11X509PublicKeyCertificate = new X509PublicKeyCertificate();
pkcs11X509PublicKeyCertificate.getToken().setBooleanValue(Boolean.TRUE);
pkcs11X509PublicKeyCertificate.getPrivate().setBooleanValue(Boolean.FALSE);
pkcs11X509PublicKeyCertificate.getLabel().setCharArrayValue("test".toCharArray());
pkcs11X509PublicKeyCertificate.getSubject().setByteArrayValue(cert.getSubjectX500Principal().getEncoded());
pkcs11X509PublicKeyCertificate.getId().setByteArrayValue(objectId);
pkcs11X509PublicKeyCertificate.getIssuer().setByteArrayValue(cert.getIssuerX500Principal().getEncoded());
// serial number should be an DER encoded ASN.1 integer
/*
INTEGER asn1Integer = new INTEGER(userCertificate.getSerialNumber());
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
DerCoder.encodeTo(asn1Integer, buffer);
pkcs11X509PublicKeyCertificate.getSerialNumber().setByteArrayValue(buffer.toByteArray());
*/
// Netscape deviates from the standard here, for use with Netscape rather use
pkcs11X509PublicKeyCertificate.getSerialNumber().setByteArrayValue(cert.getSerialNumber().toByteArray());
pkcs11X509PublicKeyCertificate.getValue().setByteArrayValue(cert.getEncoded());
session.createObject(pkcs11X509PublicKeyCertificate);
The ID of the certificate object should be the same as the ID of generated keys.

Can BouncyCastle convert a P12 to PEM

A CA gives me a P12 which I want to convert to PEM inside a jvm.
Yes using openssl command works:
openssl pkcs12 -in jack.p12 -out jack.pem -nodes -clcerts
But then it gets ugly getting key and keystore passwords into the openssl program from java not to mention unsecure.
so BouncyCastle seems to be best crypto API for java...
How could it be done (convert P12 to PEM) using bouncy...
Here is an example:
private File createPem(final Certificate certP12, final String name) {
File file = new File(getFileName(name, "pem"));
FileWriter fileWriter;
try {
fileWriter = new FileWriter(file);
PEMWriter pemWriter = new PEMWriter(fileWriter);
pemWriter.writeObject(certP12);
pemWriter.flush();
pemWriter.close();
fileWriter.close();
} catch (IOException e) {
log.error("", e);
}
return file;
}
Load the certificate as Org.BouncyCastle.X509.X509Certificate
Convert to pem.
public static Org.BouncyCastle.X509.X509Certificate ImportCertFromPfx(string path, string password)
{
Pkcs12Store store = new Pkcs12StoreBuilder().Build();
store.Load(File.OpenRead(path), password.ToCharArray());
string alias = null;
foreach (string str in store.Aliases)
{
if (store.IsKeyEntry(str))
alias = str;
}
if (alias == null)
{
Console.WriteLine("alias is null");
}
else
Console.WriteLine(alias);
X509CertificateEntry certEntry = store.GetCertificate(alias);
Org.BouncyCastle.X509.X509Certificate x509cert = certEntry.Certificate;
return x509cert;
}
Org.BouncyCastle.X509.X509Certificate x509cert = ImportCertFromPfx(p12path, p12password);
StringBuilder CertPem = new StringBuilder();
PemWriter CSRPemWriter = new PemWriter(new StringWriter(CertPem));
CSRPemWriter.WriteObject(x509cert);
CSRPemWriter.Writer.Flush();
//get Cert text
var CertPemText = CertPem.ToString();
Console.WriteLine(CertPemText);