Create CSR using PKCS10 and sign with RSA keys In Swift - swift

I generated RSA keys and my backend sends 3 parameters in BASE64 (except signatureAlgorithm) for creating CSR to me:
"subject" : "MIGfMQswCQYDVQQGEwJJUjEvMC0GA1UEAwwmMTAwMDAwMzg1MDA3NjAxMy3YqNmH2LLYp9ivINi12KfYr9mC24wxGTAXBgNVBAUTEDEwMDAwMDM4NTAwNzYwMTMxEzARBgNVBCoMCtio2YfYstin2K8xEzARBgNVBAQMCti12KfYr9mC24wxGjAYBgkqhkiG9w0BCQEWC2luZm9AdWlkLmly",
"extensions" : "MDMwDgYDVR0PAQH/BAQDAgXgMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMCMAkGA1UdEQQCMAA="
"signatureAlgorithm" : "SHA256_WITH_RSA"
I have sample code in Android/java using BouncyCastle to do this:
byte[] subjectBytes = EncodingUtils.decode(receivedSubject);
byte[] extensionsBytes = EncodingUtils.decode(receivedExtensions);
X500Name subject = X500Name.getInstance(ASN1Primitive.fromByteArray(subjectBytes));
Extensions extensions = Extensions.getInstance(ASN1Primitive.fromByteArray(extensionsBytes));
PKCS10CertificationRequestBuilder p10Builder = new JcaPKCS10CertificationRequestBuilder(subject, publicKey);
if (extensions != null)
p10Builder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, extensions);
ContentSigner signer = new ContentSigner() {
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
#Override
public AlgorithmIdentifier getAlgorithmIdentifier() {
return new DefaultSignatureAlgorithmIdentifierFinder()
.find(receivedAlgorithm);
}
#Override
public OutputStream getOutputStream() {
return this.outputStream;
}
#Override
public byte[] getSignature() {
try {
byte[] tbs = ((ByteArrayOutputStream) getOutputStream()).toByteArray();
return SignatureHelper.sign(privateKey, tbs,
csrFormat.getSignatureProfile().getSignatureAlgorithm());
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
throw new CsrGenerationException();
}
}
};
return p10Builder.build(signer).getEncoded();
How can I do the same in iOS with swift?
Is there any library to accept subject and extensions to create CSR and sign it?

Related

How to encrypt data in one app and decrypt it in different Windows app with RSA keys tied to local system?

I have a setup where I need to encrypt blob of data in one app and decrypt it in different app.
I built a sample app that creates a named CngKey object. Then create a RSACng using CngKey object. Then use RSACng object to do encryption/decryption. What I found is that the key changes across restarts of the application even though it is loaded using the name it was created with. I am lost trying to understand the relation between CngKey and RSACng objects.
Below is snippet of code that describes what I am trying to do:
using System;
using System.IO;
using System.Security.Cryptography;
namespace TPMCrypto
{
class Program
{
static byte[] data = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
static byte[] privateKey;
private static byte[] encrypted;
private static byte[] decrypted;
static void Main(string[] args)
{
const string MyKey = "MyRSAKey";
CngKey cngKey = null;
string cmd = args.Length > 0 ? args[0] : "";
try
{
CngKeyCreationParameters cng = new CngKeyCreationParameters
{
KeyUsage = CngKeyUsages.AllUsages,
KeyCreationOptions = CngKeyCreationOptions.MachineKey,
Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider
};
if (!CngKey.Exists(MyKey, CngProvider.MicrosoftSoftwareKeyStorageProvider, CngKeyOpenOptions.MachineKey))
{
Console.WriteLine("Creating rsaKey");
cngKey = CngKey.Create(CngAlgorithm.Rsa, MyKey, cng);
}
else
{
Console.WriteLine("Opening rsaKey");
cngKey = CngKey.Open(MyKey, CngProvider.MicrosoftSoftwareKeyStorageProvider, CngKeyOpenOptions.MachineKey);
}
RSACng rsaKey = new RSACng(cngKey)
{
KeySize = 2048
};
privateKey = rsaKey.Key.Export(CngKeyBlobFormat.GenericPrivateBlob);
string prvResult = ByteArrayToHexString(privateKey, 0, privateKey.Length);
Console.WriteLine("\nPrivate key - length = " + privateKey.Length + "\n" + prvResult + "\n");
const string FILE_PATH = #"\temp\tpmtests\encryptedblob.dat";
// Encrypt / decrypt
if (cmd == "readfromfile")
{
Directory.CreateDirectory(Path.GetDirectoryName(FILE_PATH));
encrypted = File.ReadAllBytes(FILE_PATH);
}
else if (cmd == "deletekey")
{
cngKey.Delete();
return;
}
else
{
encrypted = Encrypt(rsaKey, data);
Console.WriteLine("The encrypted blob: ");
Console.WriteLine(ByteArrayToHexString(encrypted, 0, encrypted.Length));
File.WriteAllBytes(FILE_PATH, encrypted);
}
decrypted = Decrypt(rsaKey, encrypted);
bool result = ByteArrayCompare(data, decrypted);
if (result)
Console.WriteLine("Encrypt / decrypt works");
else
Console.WriteLine("Encrypt / decrypt fails");
}
catch (Exception e)
{
Console.WriteLine("Exception " + e.Message);
}
finally
{
if (cngKey != null)
cngKey.Dispose();
}
Console.ReadLine();
}
static bool ByteArrayCompare(byte[] a1, byte[] a2)
{
if (a1.Length != a2.Length)
return false;
for (int i = 0; i < a1.Length; i++)
if (a1[i] != a2[i])
return false;
return true;
}
public static string ByteArrayToHexString(byte[] bytes, int start, int length)
{
string delimitedStringValue = BitConverter.ToString(bytes, start, length);
return delimitedStringValue.Replace("-", "");
}
public static byte[] Sign512(byte[] data, byte[] privateKey)
{
CngKey key = CngKey.Import(privateKey, CngKeyBlobFormat.GenericPrivateBlob);
RSACng crypto = new RSACng(key);
return crypto.SignData(data, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
}
public static bool VerifySignature512(byte[] data, byte[] signature, byte[] publicKey)
{
CngKey key = CngKey.Import(publicKey, CngKeyBlobFormat.GenericPublicBlob);
RSACng crypto = new RSACng(key);
return crypto.VerifyData(data, signature, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
}
public static byte[] Encrypt(byte[] publicKey, byte[] data)
{
CngKey key = CngKey.Import(publicKey, CngKeyBlobFormat.GenericPublicBlob);
RSACng crypto = new RSACng(key);
var result = Encrypt(crypto, data);
return result;
}
public static byte[] Encrypt(RSACng crypto, byte[] data)
{
if (null == crypto)
return null;
var result = crypto.Encrypt(data, RSAEncryptionPadding.OaepSHA512);
return result;
}
public static byte[] Decrypt(byte[] privateKey, byte[] data)
{
CngKey key = CngKey.Import(privateKey, CngKeyBlobFormat.GenericPrivateBlob);
RSACng crypto = new RSACng(key);
var result = Decrypt(crypto, data);
return result;
}
public static byte[] Decrypt(RSACng aKey, byte[] data)
{
if (null == aKey)
return null;
var result = aKey.Decrypt(data, RSAEncryptionPadding.OaepSHA512);
return result;
}
}
}
I am aware of dpapi and how to do this using it. I don't want to use it for this, please don't point me in that direction. I am using CNG flavor of crypto to force C# use NCryptXYZ crypto calls and the desire is to secure the keys in TPM.
Ah, looking at your code again, you've made a goof.
RSACng rsaKey = new RSACng(cngKey)
{
KeySize = 2048
};
Setting the KeySize property on an RSACng does one of two things:
If get_KeySize == value, ignore the input, do nothing.
Else, detach from the current key and the next time the key is used, generate a new key of get_KeySize at the time.
So you're opening an existing key, then discarding it, and generating a new ephemeral key. (Which you could see by checking rsaKey.Key.Name, it won't match your input).
Presumably you did this as a way to create the key with the right size in the first place, but you're too late. The correct way is
CngKeyCreationParameters cng = new CngKeyCreationParameters
{
KeyUsage = CngKeyUsages.AllUsages,
KeyCreationOptions = CngKeyCreationOptions.MachineKey,
Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider,
Parameters =
{
new CngProperty("Length", BitConverter.GetBytes(2048), CngPropertyOptions.Persist),
},
};

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);
}

Created OAuth bearer token generated with jwt token is invalid for REST calls

I am new to DocuSign and the REST-API. I created a developer account and added a new "Apps and Keys" entry for my application (Authentication = Implicit Grant and RSA key pairs). The keys were stored in two seperate files.
I activated the Keys using the following URL:
http://account-d.docusign.com/oauth/auth?response_type=code&scope=signature%20impersonation&client_id=_the_integration_key&redirect_uri=http://localhost
I am trying to write a JAVA application without spring security framework (or any other framework).
To read the key files I used and modified (a little bit) the functions from the DocuSign examples.
private static RSAPublicKey readPublicKeyFromFile(String filepath, String algorithm) throws IOException {
File pemFile = new File(filepath);
if (!pemFile.isFile() || !pemFile.exists()) {
throw new FileNotFoundException(String.format("The file '%s' doesn't exist.", pemFile.getAbsolutePath()));
}
PemReader reader = new PemReader(new FileReader(pemFile));
try {
PemObject pemObject = reader.readPemObject();
byte[] bytes = pemObject.getContent();
RSAPublicKey publicKey = null;
try {
KeyFactory kf = KeyFactory.getInstance(algorithm);
EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
publicKey = (RSAPublicKey) kf.generatePublic(keySpec);
} catch (NoSuchAlgorithmException e) {
System.out.println("Could not reconstruct the public key, the given algorithm could not be found.");
} catch (InvalidKeySpecException e) {
System.out.println("Could not reconstruct the public key");
}
return publicKey;
} finally {
reader.close();
}
}
private static RSAPrivateKey readPrivateKeyFromFile(String filepath, String algorithm) throws IOException {
File pemFile = new File(filepath);
if (!pemFile.isFile() || !pemFile.exists()) {
throw new FileNotFoundException(String.format("The file '%s' doesn't exist.", pemFile.getAbsolutePath()));
}
PemReader reader = new PemReader(new FileReader(pemFile));
try {
PemObject pemObject = reader.readPemObject();
byte[] bytes = pemObject.getContent();
RSAPrivateKey privateKey = null;
try {
Security.addProvider(new BouncyCastleProvider());
KeyFactory kf = KeyFactory.getInstance(algorithm, "BC");
EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
privateKey = (RSAPrivateKey) kf.generatePrivate(keySpec);
} catch (NoSuchAlgorithmException e) {
System.out.println("Could not reconstruct the private key, the given algorithm could not be found.");
} catch (InvalidKeySpecException e) {
System.out.println("Could not reconstruct the private key");
} catch (NoSuchProviderException e) {
System.out.println("Could not reconstruct the private key, invalid provider.");
}
return privateKey;
} finally {
reader.close();
}
}
private static RSAPrivateKey readPrivateKeyFromByteArray(byte[] privateKeyBytes, String algorithm) throws IOException {
PemReader reader = new PemReader(new StringReader(new String(privateKeyBytes)));
try {
PemObject pemObject = reader.readPemObject();
byte[] bytes = pemObject.getContent();
RSAPrivateKey privateKey = null;
try {
Security.addProvider(new BouncyCastleProvider());
KeyFactory kf = KeyFactory.getInstance(algorithm, "BC");
EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
privateKey = (RSAPrivateKey) kf.generatePrivate(keySpec);
} catch (NoSuchAlgorithmException e) {
System.out.println("Could not reconstruct the private key, the given algorithm could not be found.");
} catch (InvalidKeySpecException e) {
System.out.println("Could not reconstruct the private key");
} catch (NoSuchProviderException e) {
System.out.println("Could not reconstruct the private key, invalid provider.");
}
return privateKey;
} finally {
reader.close();
}
}
To get the JWT token I used the following function:
public static String generateJWTAssertion(String publicKeyFilename, String privateKeyFilename, String oAuthBasePath, String clientId, String userId, long expiresIn) throws JWTCreationException, IOException {
String token = null;
if (expiresIn <= 0L) {
throw new IllegalArgumentException("expiresIn should be a non-negative value");
}
if (publicKeyFilename == null || "".equals(publicKeyFilename) || privateKeyFilename == null || "".equals(privateKeyFilename) || oAuthBasePath == null || "".equals(oAuthBasePath) || clientId == null || "".equals(clientId)) {
throw new IllegalArgumentException("One of the arguments is null or empty");
}
try {
RSAPublicKey publicKey = readPublicKeyFromFile(publicKeyFilename, "RSA");
RSAPrivateKey privateKey = readPrivateKeyFromFile(privateKeyFilename, "RSA");
Algorithm algorithm = Algorithm.RSA256(publicKey, privateKey);
long now = System.currentTimeMillis();
token = JWT.create()
.withIssuer(clientId) // integration key
.withSubject(userId) // null
.withAudience(oAuthBasePath) // account-d.docusign.com
.withNotBefore(new Date(now))
.withExpiresAt(new Date(now + expiresIn * 1000))
.withClaim("scope", "signature impersonation")
.sign(algorithm);
} catch (JWTCreationException e){
throw e;
} catch (IOException e) {
throw e;
}
return token;
}
I checked the generated token on https://jwt.io/ and the content looks fine.
To get the bearer token I use the following code:
public Boolean getBearer(long expiresIn) throws IOException {
String jwtToken = JwtUtils.generateJWTAssertion(
RESOURCES_DIR + "public.key",
RESOURCES_DIR + "private.key",
oAuthBasePath,
integrationKey,
null,
expiresIn
);
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("text/plain");
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer")
.addFormDataPart("assertion", jwtToken)
.build();
Request request = new Request.Builder()
.url("https://" + oAuthBasePath + "/oauth/token") // https://account-d.docusign.com/oauth/token
.method("POST", body)
.build();
Response response = client.newCall(request).execute();
int responseCode = response.code();
String responseText = response.body().string();
Gson gson = new Gson();
OAuthResponse oAuthResponse = gson.fromJson(responseText, OAuthResponse.class);
if (responseCode >= 200 && responseCode <= 299) {
bearerToken = oAuthResponse.getAccess_token();
return true;
}
System.out.println("Errorcode: " + oAuthResponse.getError());
System.out.println("Error: " + oAuthResponse.getError_description());
return false;
}
I get the bearer token and want to use it for the following REST calls.
For example:
public void getUsers () throws IOException {
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
Request request = new Request.Builder()
.url(getRestBaseUrl() +"/users") // https://demo.docusign.net/restapi/v2.1/accounts/_API_account_id/users
.method("GET", null)
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + bearerToken)
.build();
Response response = client.newCall(request).execute();
String responseText = response.body().string();
System.out.println(responseText);
}
But instead of a JSON structure with the users of my developer account, I got the following response:
{"errorCode":"AUTHORIZATION_INVALID_TOKEN","message":"The access token provided is expired, revoked or malformed. Authentication for System Application failed."}
When I use the API explorer and the bearer token, I can use it for authentication (it is shown as valid), but the REST call for "users" get the same error response.
So I used the API explorer for login and the REST call works.
I used the bearer token from the API explorer and used it (as fixed entered string value) as bearer token. And the JAVA REST calls works.
So, there must be an error in generating / requesting the JWT token or bearer token.
Any idea what's wrong?
Regards,
Rainer
I found the reason.
The API username was missing.
String jwtToken = JwtUtils.generateJWTAssertion(
RESOURCES_DIR + "public.key",
RESOURCES_DIR + "private.key",
oAuthBasePath,
integrationKey,
"_here_the_API_username",
expiresIn
);
After adding the username I could use the API.

How to generate signature using hash string using iTextSharp and c#

I am trying to add public key string in MakeSignature.SignExternalContainer but having error,
string sing_test = "MIIFMTCCBBmgAwIBAgICMF8wDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCSU4xKjAoBgNVBAoTIU5TREwgZS1Hb3YgSW5mcmFzdHJ1Y3R1cmUgTGltaXRlZDEdMBsGA1UECxMUQ2VydGlmeWluZyBBdXRob3JpdHkxIjAgBgNVBAMTGU5TRExlR292SXNzdWluZ0NBMjAxNlRlc3QwHhcNMTcwMTI4MDkwOTEzWhcNMTcwMTI4MDkzODEzWjCCARgxCzAJBgNVBAYTAklOMR0wGwYDVQQDExRNQU5JU0ggR0lSSVNIIEJFTkRSRTEpMCcGA1UEQRMgMjUxYjkyYjkxZjllNDBmOGE2YmVlZjZiMDgyMzYyZGYxNjA0BgNVBC0DLQBsbnlOOVVuNzE5S1NKNnpaQVNtUGZaUlJpYTVuTXBLSEV0cs3ZidAmwZQKbBmUKLoeD8nCDIUZZR9Am2pwSnar7WtB2MA74Sz4U2xzifNsh22YPd+ySbGqJtUd9xbhlQIDAQABo4IBHTCCARkwEQYDVR0OBAoECEwFNGCDXdKgMIG7BgNVHSAEgbMwgbAwga0GB2CCZGQCBAIwgaEwQQYIKwYBBQUHAgEWNWh0dHBzOi8vbnNkbC5lZ292LWNhLmNvLmluL3JlcG9zaXRvcnkvbnNkbGVnb3ZjcHMucGRmMFwGCCsGAQUFBwICMFAaTkFhZGhhYXIgZS1LWUMtQmlvbWV0cmljIENsYXNzIENlcnRpZmljYXRlIElzc3VlZCBieSBOU0RMIGUtR292IElzc3VpbmcgQ0EgVGVzdDAhBgNVHREEGjAYgRZtYW5pc2hiZW5kcmVAZ21haWwuY29tMBMGA1UdIwQMMAqACEBuFJI2LqIcMA4GA1UdDwEB/wQEAwIGwDANBgkqhkiG9w0BAQsFAAOCAQEADbuOkgWKquflIrqDsB93L5aa+VxjFHvB914UDIllO4MYTo/UVgDN2iANiJ2HOjFkY0VhdnuJKp0cjDSywP6mTXs0VUf70DEL5sZpjfnoJK++Eb6FlDHHMKflMkG/ja3b6FWK1W/1L0/yjYpjl4E2Uu5tq0T3k4ZOPd/LBD3OeudKZM1IPaT95Zd8JRqwz6LsyYx1SvXqLtrRUb8eIauvAJ92prvovxusvupzolB3AOCkwEr6jqGXOiwssEnqUCuUd3CVXWUxL5TzWW9oCPIDAKbUyyVWtntorVFfKmzvWDCV42jkHrf9J1snbr4DyjNhkOSQr6cDZfg0uK2gKWfBcA==";
byte[] rawData = System.Convert.FromBase64String(sing_test );
public static byte[] GetBytesToSign(string unsignedPdf, string tempPdf, string signatureFieldName)
{
using (PdfReader reader = new PdfReader(unsignedPdf))
{
using (FileStream os = File.OpenWrite(tempPdf))
{
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.SetVisibleSignature(new iTextSharp.text.Rectangle(36, 748, 144, 780), 1, signatureFieldName);
IExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKMS, PdfName.ADBE_PKCS7_SHA1);
MakeSignature.SignExternalContainer(appearance, external, 8192);
stamper.Close();
return SHA1Managed.Create().ComputeHash(appearance.GetRangeStream());
}
}
}
public static void EmbedSignature(string tempPdf, string signedPdf, string signatureFieldName, byte[] signedBytes)
{
using (PdfReader reader = new PdfReader(tempPdf))
{
using (FileStream os = File.OpenWrite(signedPdf))
{
PdfStamper st = PdfStamper.CreateSignature(reader, os, '\0', null, true);
PdfSignatureAppearance sap = st.SignatureAppearance;
sap.Reason = "Testing";
sap.Location = "Test";
sap.SetVisibleSignature(new iTextSharp.text.Rectangle(250, 50, 50, 100), 1, null);
IExternalSignatureContainer external = new MyExternalSignatureContainer(signedBytes);
try
{
MakeSignature.SignExternalContainer(sap, external, 8192);
}
catch (Exception ex) { }
st.Close();
}
}
}
private class MyExternalSignatureContainer : IExternalSignatureContainer
{
private readonly byte[] signedBytes;
public MyExternalSignatureContainer(byte[] signedBytes)
{
this.signedBytes = signedBytes;
}
public byte[] Sign(Stream data)
{
return signedBytes;
}
public void ModifySigningDictionary(PdfDictionary signDic)
{
}
}
getting error..
Error during signature verification.
Error encountered while BER decoding:
Thanks...

Get ExtensionValue from x509Certificate

I use bouncycastle in Java
CertificateFactory.getInstance("X509", "BC")
certFactory.generateCertificate(in)
to generate the cert. It works fine. But when I use
x509Certificate.getExtensionValue("1.2.3.4.5.6.7")
The return value does not match the membersrvc's one.
Did I miss some thing?
With bouncycastle you can do this to extract the ASN1 structure of the extension
public ASN1Primitive getExtensionValue(X509Certificate certificate, String oid) throws IOException {
byte[] bytes = certificate.getExtensionValue(oid);
if (bytes == null) {
return null;
}
ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(bytes));
ASN1OctetString octs = (ASN1OctetString) aIn.readObject();
aIn = new ASN1InputStream(new ByteArrayInputStream(octs.getOctets()));
return aIn.readObject();
}
ASN1 is a complex object, you need to parse it to get the desired field. For example to Give back the CA URI meta-data found within the given X509 cert.
public String getIssuerURL(final X509Certificate certificate) throws Exception {
final ASN1ObjectIdentifier ocspAccessMethod = X509ObjectIdentifiers.id_ad_caIssuers;
final byte[] authInfoAccessExtensionValue = certificate.getExtensionValue(Extension.authorityInfoAccess.getId());
if (null == authInfoAccessExtensionValue) {
return null;
}
ASN1InputStream ais1 = null;
ASN1InputStream ais2 = null;
try {
final ByteArrayInputStream bais = new ByteArrayInputStream(authInfoAccessExtensionValue);
ais1 = new ASN1InputStream(bais);
final DEROctetString oct = (DEROctetString) (ais1.readObject());
ais2 = new ASN1InputStream(oct.getOctets());
final AuthorityInformationAccess authorityInformationAccess = AuthorityInformationAccess.getInstance(ais2.readObject());
final AccessDescription[] accessDescriptions = authorityInformationAccess.getAccessDescriptions();
for (AccessDescription accessDescription : accessDescriptions) {
final boolean correctAccessMethod = accessDescription.getAccessMethod().equals(ocspAccessMethod);
if (!correctAccessMethod) {
continue;
}
final GeneralName gn = accessDescription.getAccessLocation();
if (gn.getTagNo() != GeneralName.uniformResourceIdentifier) {
continue;
}
final DERIA5String str = (DERIA5String) ((DERTaggedObject) gn.toASN1Primitive()).getObject();
final String accessLocation = str.getString();
return accessLocation;
}
return null;
} catch (IOException e) {
throw new Exception(e);
} finally {
IOUtils.closeQuietly(ais1);
IOUtils.closeQuietly(ais2);
}
}
To return a human-readable string from an ASN1Primitive
public String getStringFromGeneralName(ASN1Primitive names) throws IOException {
ASN1TaggedObject taggedObject = (ASN1TaggedObject) names ;
return new String(ASN1OctetString.getInstance(taggedObject, false).getOctets(), "ISO-8859-1");
}