I'm trying to create certificate requests according to PKCS#10.
X509v3 Key Usage should be set to: Digital Signature, Key Encipherment.
This is what I've found so far, but since I use latest bouncycastle (1.52) the X509Extension.keyUsage is deprecated.
public static PKCS10CertificationRequest generateCSRFile(KeyPair keyPair, KeyUsage keyUsage) throws IOException, OperatorCreationException {
String principal = "CN=" + Utils.getCertificateCommonName() + ", O=" + Utils.getCertificateOrganization();
AsymmetricKeyParameter privateKey = PrivateKeyFactory.createKey(keyPair.getPrivate().getEncoded());
AlgorithmIdentifier signatureAlgorithm = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1WITHRSA");
AlgorithmIdentifier digestAlgorithm = new DefaultDigestAlgorithmIdentifierFinder().find("SHA-1");
ContentSigner signer = new BcRSAContentSignerBuilder(signatureAlgorithm, digestAlgorithm).build(privateKey);
PKCS10CertificationRequestBuilder csrBuilder = new JcaPKCS10CertificationRequestBuilder(new X500Name(principal), keyPair.getPublic());
ExtensionsGenerator extensionsGenerator = new ExtensionsGenerator();
extensionsGenerator.addExtension(X509Extension.basicConstraints, true, new BasicConstraints(true));
extensionsGenerator.addExtension(X509Extension.keyUsage, true, keyUsage);
csrBuilder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, extensionsGenerator.generate());
PKCS10CertificationRequest csr = csrBuilder.build(signer);
return csr;
}
Is there another way to add KeyUsage?
Basically this is what I'm trying to achieve:
Generate certificate requests with PKCS#10
Create two certificates from two keypairs (Digital Signature + Key Encipherment and Non Repudiation).
Save the private keys from the certificate requests in PKCS#12.
I'm quite new when it comes to cryptography.
Does this work for you? X509Extension seems to be replaceable with Extension. Not sure on the Android context though.
public static PKCS10CertificationRequest generateCSRFile(KeyPair keyPair, KeyUsage keyUsage) throws IOException, OperatorCreationException {
String principal = "CN=" + Utils.getCertificateCommonName() + ", O=" + Utils.getCertificateOrganization();
AsymmetricKeyParameter privateKey = PrivateKeyFactory.createKey(keyPair.getPrivate().getEncoded());
AlgorithmIdentifier signatureAlgorithm = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1WITHRSA");
AlgorithmIdentifier digestAlgorithm = new DefaultDigestAlgorithmIdentifierFinder().find("SHA-1");
ContentSigner signer = new BcRSAContentSignerBuilder(signatureAlgorithm, digestAlgorithm).build(privateKey);
PKCS10CertificationRequestBuilder csrBuilder = new JcaPKCS10CertificationRequestBuilder(new X500Name(principal), keyPair.getPublic());
ExtensionsGenerator extensionsGenerator = new ExtensionsGenerator();
extensionsGenerator.addExtension(Extension.basicConstraints, true, new BasicConstraints(true));
extensionsGenerator.addExtension(Extension.keyUsage, true, keyUsage);
csrBuilder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, extensionsGenerator.generate());
PKCS10CertificationRequest csr = csrBuilder.build(signer);
return csr;
}
Related
I have a app in Android which communicates with a server that Signs a certificate Signing Request and returns the signed certificate so that I can be used by the client in further calls.
Recently we are trying to move to Flutter (Dart) and I'm trying to replicate the creation of the CSR, but I'm a little lost since I'm relatively new with Dart.
I would appreciate if you could point me in the right direction.
Here's what the function that creates the CSR looks like:
public String createPKI(String mdnString) {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
//KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ECDSA", "SC");
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("prime256v1");
keyPairGenerator.initialize(ecGenSpec, new SecureRandom());
KeyPair kp = keyPairGenerator.generateKeyPair();
publicKey = kp.getPublic();
privateKey = kp.getPrivate();
PKCS10CertificationRequest kpGen = new PKCS10CertificationRequest("SHA256withECDSA", new X509Name(String.format("UID=%s", mdnString)), publicKey, null, privateKey); //mdnString is a phone number including the international code.
String certRequest = Base64.encodeToString(kpGen.getEncoded(), Base64.DEFAULT);
certRequest = certRequest.replace("\n", "");
return certRequest;
} catch(Exception e) {
if (Constants.DEBUG) {
Log.v("Exception", e.getMessage());
}
return null;
}
}
The string that I get from this function is sent to the server so it can be signed and then the cert is returned in the response.
Any help would be appreciated.
Look into the basic utils package: https://pub.dev/packages/basic_utils.
It contains several utility classes, including X509Utils and CryptoUtils, which you can use to generate your keypair and CSR. The snippet below should provide some reference:
import 'package:basic_utils/basic_utils.dart';
...
const Map<String, String> X509_SUBJECT = {
'CN': '...',
'C': '...',
'ST': '...',
'L': '...',
'O': '...',
'OU': '...',
};
AsymmetricKeyPair keyPair = CryptoUtils.generateEcKeyPair();
X509Utils.generateRsaCsrPem(X509_SUBJECT, keypair.privateKey, keypair.publicKey);
I'm trying to store a short piece of text inside Android's Secure element using the following code:
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
PasswordProtection keyStorePP = new KeyStore.PasswordProtection(null);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEwithHmacSHA1");
SecretKey generatedSecret = factory.generateSecret(newPBEKeySpec(mySecureText.toCharArray()));
ks.setEntry("alias", new KeyStore.SecretKeyEntry(generatedSecret), keyStorePP);
The code above gives the following exception:
08-17 14:39:32.832: W/System.err(11713): java.security.KeyStoreException: Unsupported protection parameter class: java.security.KeyStore$PasswordProtection. Supported: android.security.keystore.KeyProtection
Is there something I'm doing wrong or just AndroidKeyStore does not support storing strings?
Last thing, if I'll switch to BKS the code will execute.
Thanks.
The error tells you to change this:
PasswordProtection keyStorePP = new KeyStore.PasswordProtection(null);
To this
PasswordProtection keyStorePP = new KeyStore.KeyProtection();
KeyProtection cant set null password.
char[] password = {'p','a','s','s'};
KeyStore.ProtectionParameter protParam =
new KeyStore.PasswordProtection(password);
ks.setEntry("alias", new KeyStore.SecretKeyEntry(generatedSecret), keyStorePP);
I got this to work below. This is how you specify new KeyProtection:
import android.security.keystore.KeyProtection;
import android.security.keystore.KeyProperties;
...............
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null, null);
SecureRandom secureRandom = new SecureRandom(mySecureText.getBytes());
KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES);
keyGenerator.init(256, secureRandom);
SecretKeySpec keySpec = new SecretKeySpec(keyGenerator.generateKey().getEncoded(), KeyProperties.KEY_ALGORITHM_AES);
keyStore.setEntry(alias, new SecretKeyEntry(keySpec),
new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setRandomizedEncryptionRequired(false)
.build()
);
I've created a key pair, stored the private key in the AndroidKeystore.
Generated a CSR using the Public key from the key pair
Exported the CSR to the CA, and got it to generate a cert
Installed the cert on the phone
Now, I'm trying to associate the private key from #1 with the cert that was installed at step #4.
Have looked all day, cannot find a mechanism to do it. Android documentation suggests using the KeyStore.setKeyEntry method. I intend to use it but am unable to read the cert that was installed.
I can display all certs in the AndroidCAStore, and I do see this newly installed cert in the "User certificates" section on the phone but am unable to read it programatically. Any ideas ?
Trying to do pretty much the same thing. The key association with the signed cert also works using keystore.setEntry. What I can't get to work is this user cert then to appear in the "IPSec User certificate" listbox when trying to add a VPN. Running on Marshmallow 6.0.1
My logic looks like this
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyGen = KeyPairGenerator.getInstance("EC", "AndroidKeyStore");
keyGen.initialize(
new KeyGenParameterSpec.Builder(
"myAlias",
KeyProperties.PURPOSE_SIGN)
.setAlgorithmParameterSpec(new ECGenParameterSpec("secp384r1"))
.setDigests(KeyProperties.DIGEST_SHA256,
KeyProperties.DIGEST_SHA384,
KeyProperties.DIGEST_SHA512)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setUserAuthenticationRequired(false)
.setKeyValidityStart(now)
.setKeyValidityForOriginationEnd(nowPlusThreeYears)
.build());
keyPair = keyGen.generateKeyPair();
privateKey = (PrivateKey) keyStore.getKey("myAlias", null);
publicKey = keyStore.getCertificate("myAlias").getPublicKey();
Certificate[] chain = keyStore.getCertificateChain("myAlias");
keyStore.setKeyEntry("myAlias", privateKey, null, chain);
StringBuilder x500PrincipalBuilder = new StringBuilder("CN=");
x500PrincipalBuilder.append("My Company");
x500PrincipalBuilder.append(", ");
x500PrincipalBuilder.append("L=");
x500PrincipalBuilder.append("My Location");
x500PrincipalBuilder.append(", ");
x500PrincipalBuilder.append("ST=");
x500PrincipalBuilder.append("CA");
x500PrincipalBuilder.append(", ");
x500PrincipalBuilder.append("O=");
x500PrincipalBuilder.append("My Org");
x500PrincipalBuilder.append(", ");
x500PrincipalBuilder.append("OU=");
x500PrincipalBuilder.append("my ou");
x500PrincipalBuilder.append(", ");
x500PrincipalBuilder.append("C=");
x500PrincipalBuilder.append("US");
Signature ecdsaSignature = Signature.getInstance("SHA384withECDSA");
ecdsaSignature.initSign(keyPair.getPrivate());
byte[] strByte = new byte[0];
strByte = x500PrincipalBuilder.toString().getBytes(UTF8_CHARSET);
ecdsaSignature.update(strByte);
X500Principal x500Principal = new X500Principal(x500PrincipalBuilder.toString());
PKCS10CertificationRequestBuilder p10Builder = new JcaPKCS10CertificationRequestBuilder(
x500Principal, keyPair.getPublic());
JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder(signatureGenerator.getSigningAlgorithm());
ContentSigner signer = csBuilder.build(keyPair.getPrivate());
org.bouncycastle.pkcs.PKCS10CertificationRequest csr = p10Builder.build(signer);
PemObject pemObject = new PemObject("CERTIFICATE REQUEST", csr.getEncoded());
StringWriter str = new StringWriter();
PEMWriter pemWriter = new PEMWriter(str);
pemWriter.writeObject(pemObject);
pemWriter.close();
str.close();
// write the csr to a file
// get it signed by the CA (Microsoft CA)
// Push the cert to the phone
// Install the cert
Certificate clientCertSignedByCA = CertificateFactory.getInstance("X.509").generateCertificate(new FileInputStream("/path/to/cert.cer));
KeyStore.Entry entry = keyStore.getEntry("myAlias", null);
PrivateKey privateKey = (PrivateKey) keyStore.getKey("myAlias", null);
Certificate[] chain = new Certificate[1];
chain[0] = clientCertSignedByCA;
keyStore.setKeyEntry("myAlias", privateKey, null, chain);
I have been trying to encrypt a string in android with private key and decrypt in node js with public key.
private final static String PRIVATE_KEY = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDxJtyHARAMe69K0OoqoO+1yfXr\n" +
"jfWFums8HLOjArJNyVJapUC4Dr0Rcj0e4wAy1QCQJsxCl8OeitiVAugoML39ZdCMPENc9u/LEGVU\n" +
"lCB8B3tjB9FoDWzKEqI6CXP5Ga80dNRNakC7/aCUFdVdvYA+m4UNtbzP+KB+RrQQkA9TPBSm/25P\n" +
"anBkCHrmRQIeC2RQz4eTjkpSpA97fmUsTjSOUrAl94OGdZ2EiWUMZuN7lF26/DUsrLlHB15l4f12\n" +
"HfsvVyRGCkWK9pg0LLoJpCEq8IJExsrTBOT6QHT3Vx2oKFsHVp6sg2Lknk+W8ioRvLPGb6CPHu4I\n" +
"q70bCcyVLu0lAgMBAAECggEAa3aq7YqesUFo80k4IPkI+ZTffzIKyKYzZV1Q/AKWnK1rgrODrMH8\n" +
"pUqoTBxSmVRsZNC1U7O32+356CWceVSHReXaUrQEPOhaIb7TuSYtd7gJ1y7Dtb/NzBsTqhNOWCKG\n" +
"/jRV642+/UdgCL3WEGkDPmMlnt9vHaqpMrylP4BDJA6Tjef9/AcJ0Df+bn+hCA0ICs1i3PXmMWaS\n" +
"emJ/DK38caumYyuRYF/o26seU/gY0vMqwf2MH9Anb/f9RxfOtx6MlKd1SnotuYahFU0/rNSNmK/G\n" +
"oFKPFWBX3e0nTdIz4VQtiSKScHsLkaSwSBP2kN3TK2MFRpyLylOD7C7wtM+mvQKBgQD+liJhlF5T\n" +
"7C0zSQ2t0mGLkoL58U8eA8TZg2VXb/wl6FmTtQ3dQ+QhFIs4xgO+fCiZfjgA5RPLIvbP71vLHsYH\n" +
"3/R+zwkQtZy4IvT5jgK4beXsIuQVtN69rwBoWvB1XDDOZlozoG/6RvNMstHeXBH11rzQSZAFzCaJ\n" +
"u9YyIZy1HwKBgQDyfaGcaqPaso2IH/Iy7Xnu1YzsElE82KAv4tvmnzNpWWeQ8k+q8P4vwDCTR206\n" +
"D6Vt68B6UpZH5BkiyQ1CUBMU4XJR2+JXQjMQg/T1QpK0mBLOTTZhbJa+61hoKwfgmjnYTLra4yUW\n" +
"prq6jOxxAkQs0dCX5PrsI2L3/wbAJ5HxOwKBgQDAS+rARe9R+IzTthRs/QHNCOeBnzGhfDtOCJ+d\n" +
"geq1P2GZ3iIQxV0lV30pbvgZA3MvLVVj56QhxdEjkqqFLENsY08sEXnJc0RjGZRsg0WuxOPsjxY1\n" +
"Bx9Pq0XljPsfynjbDhiH8mFibAEOJ+u5x1WRmZeYxFfS6TcaxhSuXREfBQKBgQCvWmoj0nnrDHOM\n" +
"nI1ohpJGQ+dET3qvpXcxKbwbacSjyiM6jf9OfjdSEIkP9/bkpavbcUAfNNm34xrKLNmJup4R23Xv\n" +
"/DIRJ64Fo2bgdOPh9Jak2PEaQoxAQ7AKpBNuOBjccaAt6VRIrQkbHg1dK2Zhgth0/wD1AiHvdFxN\n" +
"WFARQQKBgAsPKujqLWyQjpFiqk51/mbGP0xnK6QQI4981pG9UkHRugL5EIUwe4mBSa2v9nIsqJ29\n" +
"Qk2pvaILZWUniVzcK4stbx1ML3HEcpsTi0/w49Abl0k/0ycmErey63bSgf5fszGti/MBOLVagxsa\n" +
"7srdWq2DntK5AHy7gSk+WcMiHF8v";
private final static String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8SbchwEQDHuvStDqKqDvtcn16431hbpr\n" +
"PByzowKyTclSWqVAuA69EXI9HuMAMtUAkCbMQpfDnorYlQLoKDC9/WXQjDxDXPbvyxBlVJQgfAd7\n" +
"YwfRaA1syhKiOglz+RmvNHTUTWpAu/2glBXVXb2APpuFDbW8z/igfka0EJAPUzwUpv9uT2pwZAh6\n" +
"5kUCHgtkUM+Hk45KUqQPe35lLE40jlKwJfeDhnWdhIllDGbje5Rduvw1LKy5RwdeZeH9dh37L1ck\n" +
"RgpFivaYNCy6CaQhKvCCRMbK0wTk+kB091cdqChbB1aerINi5J5PlvIqEbyzxm+gjx7uCKu9GwnM\n" +
"lS7tJQIDAQAB";
public String encryptedString(String plain) throws Exception {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(PRIVATE_KEY, Base64.DEFAULT));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey key = keyFactory.generatePrivate(keySpec);
byte[] dataToBytes = plain.getBytes("UTF-8");
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, key);
return Base64.encodeToString(cipher.doFinal(dataToBytes), Base64.DEFAULT);
}
I am encrypting with above code and trying to decrypt with below code. Its not working.
var NodeRSA = require('node-rsa');
var key = new NodeRSA();
key.importKey(privateKeyData, 'pkcs8-private');
key.importKey(publicKeyData, 'pkcs8-public');
var decrypted = key.decryptPublic(encrypted, 'utf8');
The process is:
I have generated a key pair and saved them statically on both sides.
Encrypting and Decrypting on Android and NodeJs individually works very well.
But its not working as i wanted, Asymmetric client-server encryption.
I also found that the two encrypted strings created by Android and NodeJs are not same.
Can anyone show me a solution or point me to an alternative for asymmetric encryption which works on Android and NodeJs.
I am working on mobile product. We are using the data in xml document. In order to keep our data secure we need an encryption algorithm(but we don't want the existing algorithm to import)
Can u give me some steps to encrypt the data.(if code example is most welcome).
To be more secure, you have to do with your own secret key. Try to use this code
KeyStore ks = KeyStore.getInstance();
// get the names of all keys created by our app
String[] keyNames = ks.saw("");
// store a symmetric key in the keystore
SecretKey key = Crypto.generateKey();
boolean success = ks.put("secretKey1", key.getEncoded());
// check if operation succeeded and get error code if not
if (!success) {
int errorCode = ks.getLastError();
throw new RuntimeException("Keystore error: " + errorCode);
}
// get a key from the keystore
byte[] keyBytes = ks.get("secretKey1");
SecretKey key = new SecretKeySpec(keyBytes, "AES");
// delete a key
boolean success = ks.delete("secretKey1");
If you want to develop your own encryption scheme, be prepared to embark on a research project. You can use any of standard encryption algorithms like AES/DES etc, with your private keys that are sufficiently long and difficult to crack.
public string PassEncrypt(string Password)
{
// Encrypting the password entered by User
// ======================================================
MD5 md5 = new MD5CryptoServiceProvider();
md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(Password));
byte[] result = md5.Hash;
StringBuilder strBuilder = new StringBuilder();
for (int i = 0; i < result.Length; i++)
{
strBuilder.Append(result[i].ToString("x2"));
}
return strBuilder.ToString();
// ======================================================
}
OR
You may refer on this links :
developer.motorala.com
codereview.stackexchange.com
android snippets
java-tips.org