*.rsa and *.sf manifest.mf calling from java class - java

I had resigned a jar file and runned it. However, it is closed itself immediately after opening. Is it possible to call infromation of *.rsa or *.sf or manifest.mf from java code to check it if changed or not, thank you.

Actually I found a method in the class of jar file and its returning certificates, that means yes in jar file there is a certificate control bridge, code is:
private Certificate[] XQ(et etProp) throws Exception{
System.out.println("Rg test 78");
String value = null;
Iterator iterator = etProp.af().iterator();
while (iterator.hasNext()) {
un.JI innerUn = (un.JI) iterator.next();
String certificateToUpperCase = innerUn.XQ().toUpperCase();
if (certificateToUpperCase != null && certificateToUpperCase.startsWith("META-INF/")
&& (certificateToUpperCase.endsWith(".RSA") || certificateToUpperCase.endsWith(".DSA"))) {
value = innerUn.XQ();
break;
}
}
if (value == null) {
System.out.println("Rg test 81");
qm.XQ((String) "Could not find certificates file");
return null;
} else {
System.out.println("Rg test 82");
byte[] arrayAf = etProp.af(value);
if (arrayAf == null) {
System.out.println("Rg test 83");
Object[] objectsArray = new Object[] { value };
return null;
} else {
System.out.println("Rg test 84");
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(arrayAf);
Collection collection;
try {
System.out.println("Rg test 85");
CertificateFactory certificateFactory = CertificateFactory
.getInstance("X.509");
collection = certificateFactory.generateCertificates(byteArrayInputStream);
} catch (CertificateException ex) {
qm.XQ((String) String.format(
"Could not parse certificate data: %s",
new Object[] { ex.toString() }));
return null;
}
Certificate[] certificates = new Certificate[collection.size()];
int i = 0;
Certificate certificate;
for (Iterator iterator1 = collection.iterator(); iterator1.hasNext(); certificates[i++] = certificate) {
System.out.println("Rg test 87");
certificate = (Certificate) iterator1.next();
}
return certificates;
}
}
}
It is very nice move to protect jar file from cracking.

Related

Mustang Library: Converting invalid PDFA3 to valid PDFA3 for building Factur-x

I'm trying to create a facturX using Mustang Library in a webservice. This web service accept a xml string and a base64 PDF.
My issue is that i have no "knowledge" about PDF format that is sent to me. In my service layer class, I build my facturx using ZUGFeRDExporterFromA1.
#Override
public FacturxDto createFacturX(FacturxDto facturxDto) {
context.setContext(facturxDto);
if (facturxDto.getVersion() == null) {
facturxDto.setVersion(2);
}
if(facturxDto.getPdfDocument() == null) {
throw new AppServiceException("Pdf is required in the payload");
}
if(facturxDto.getXml() == null) {
throw new AppServiceException("Xml is required in the payload");
}
if ((facturxDto.getVersion() < 1) || (facturxDto.getVersion() > 2)) {
throw new AppServiceException("invalid version");
}
try {
Utils.facturxValidator(facturxDto);
} catch (SAXException | IOException e) {
throw new AppServiceException(e.getMessage());
}
ByteArrayOutputStream output = new ByteArrayOutputStream();
log.debug("Converting to PDF/A-3u");
PDFAConformanceLevel pdfaConformanceLevel = Utils.setPdfaConformanceLevel(facturxDto);
// System.out.println(Arrays.toString(facturxDto.getPdfDocument().getBytes(StandardCharsets.UTF_8)));
byte[] xmlData = facturxDto.getXml().getBytes(StandardCharsets.UTF_8);
byte[] pdfData = Base64.getDecoder().decode(facturxDto.getPdfDocument().getBytes(StandardCharsets.UTF_8));
try {
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1()
.setProducer("Mustang LIB")
.setCreator("ME")
.setProfile(facturxDto.getFxLevel())
.setZUGFeRDVersion(facturxDto.getVersion())
.setConformanceLevel(pdfaConformanceLevel)
.ignorePDFAErrors()
.load(pdfData);
ze.attachFile("factur-x.xml", xmlData, "text/xml", "Data");
ze.setXML(xmlData);
log.debug("Attaching ZUGFeRD-Data");
ze.disableAutoClose(true);
ze.export(output);
byte[] bytes = output.toByteArray();
InputStream inputStream = new ByteArrayInputStream(bytes);
byte[] pdfBytes = IOUtils.toByteArray(inputStream);
String encoded = Base64.getEncoder().encodeToString(pdfBytes);
// persist data in db and generate id
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
FacturxEntity facturxEntity = modelMapper.map(facturxDto, FacturxEntity.class);
facturxEntity.setStatus(RequestOperationStatus.SUCCESS.name());
facturxEntity.setCreatedAt(new Date());
facturxEntity.setFacturxId(Utils.generateId());
FacturxEntity storedFacturx = facturxRepository.save(facturxEntity);
FacturxDto returnValue = modelMapper.map(storedFacturx, FacturxDto.class);
returnValue.setPdfDocument(encoded);
return returnValue;
} catch (IOException e) {
e.printStackTrace();
throw new AppServiceException(e.getMessage());
}
}
My issue is here :
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1()
.setProducer("Mustang LIB")
.setCreator("ME")
.setProfile(facturxDto.getFxLevel())
.setZUGFeRDVersion(facturxDto.getVersion())
.setConformanceLevel(pdfaConformanceLevel)
.ignorePDFAErrors()
.load(pdfData);
If i don't use ignorePDFAErrors() I do have an exception thrown.
If i use it, my pdf is not PDFA compliant. And it's an issue.
Is there a way to convert on the fly an invalid PDFA to a valid one. Thanks
You can e.g. use Mustang's REST API, Mustang Server https://www.mustangproject.org/server/ to correct and export any input PDF file as PDF/A, which also includes files which are already PDF/A-1.
kind regards
Jochen

iText7 LtvVerification.addVerification not enabling LTV

We are trying to make the signed signature LTV enabled. I am using the below code to add verification. When signature.isTsp() is false, the PDF says Signature is not LTV enabled, though in the other case (signature.isTsp() is true) it shows as valid.
When we open the PDF and try to manually add verification info by right clicking on the signature it enables LTV without any issue. Not sure what we are missing here.
Any input will be highly helpful.
// Adds LTV-enabled information to the PDF document.
private ByteArrayOutputStream addLtv(final IOcspClient ocspClient,
final ByteArrayOutputStream docStream)
throws IOException, GeneralSecurityException {
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
final InputStream signedStream = new ByteArrayInputStream(docStream.toByteArray());
final PdfReader reader = new PdfReader(signedStream);
final PdfDocument document =
new PdfDocument(reader, new PdfWriter(outputStream), new StampingProperties().useAppendMode());
final LtvVerification verification = new LtvVerification(document);
final SignatureUtil signatureUtil = new SignatureUtil(document);
final List<String> signatureNames = signatureUtil.getSignatureNames();
final String sigName = signatureNames.get(signatureNames.size() - 1);
final PdfPKCS7 signature = signatureUtil.verifySignature(sigName);
final CrlClientOnline crl = new CrlClientOnline();
if (!signature.isTsp()) {
for (final String name: signatureNames) {
addVerificationInfo(ocspClient, verification, crl, name);
}
} else {
addVerificationInfo(ocspClient, verification, crl, sigName);
}
document.close();
return outputStream;
}
private void addVerificationInfo(final IOcspClient ocspClient, final LtvVerification verification,
final CrlClientOnline crl,
final String name) throws IOException, GeneralSecurityException {
verification.addVerification(
name, ocspClient, crl,
LtvVerification.CertificateOption.WHOLE_CHAIN,
LtvVerification.Level.OCSP_CRL,
LtvVerification.CertificateInclusion.NO);
}
The main reason why your code does not always LTV-enable PDFs is that it does not add validation information related to OCSP response signatures.
It doesn't add validation information for CRL signatures, either. As CRLs usually are signed by the issuer certificate of the signer certificate, though, and as validation information for that issuer certificate have already been added in the context of the main signature, LTV-enabling usually does not fail because of missing CRL signature validation information. So if you can use CRLs only, chances are that your code indeed already does LTV-enable PDFs.
In the context of this answer (in particular its section "An approach using an own utility class") I created an utility class AdobeLtvEnabling for iText 5 allowing to LTV-enable PDFs, mostly using bits and pieces found in iText 5 itself. In contrast to your code it does add validation information for OCSP response signatures (and also for CRL signatures).
Here you can find the port of that class to iText 7.
The utility class AdobeLtvEnabling
This utility class bundles the code required for LTV enabling the signatures in a signed PDF document. The code pieces mostly have been taken from existing iText code. The main reason why this class has not been designed to derive from LtvVerification is that required variables and methods from that class are private. As the class originally has been written for iText 5, some iText-5-isms probably can be found in it...
public class AdobeLtvEnabling {
/**
* Use this constructor with a {#link PdfDocument} in append mode. Otherwise
* the existing signatures will be damaged.
*/
public AdobeLtvEnabling(PdfDocument pdfDocument) {
this.pdfDocument = pdfDocument;
}
/**
* Call this method to have LTV information added to the {#link PdfDocument}
* given in the constructor.
*/
public void enable(IOcspClient ocspClient, ICrlClient crlClient) throws OperatorException, GeneralSecurityException, IOException, StreamParsingException, OCSPException {
SignatureUtil signatureUtil = new SignatureUtil(pdfDocument);
List<String> names = signatureUtil.getSignatureNames();
for (String name : names) {
PdfPKCS7 pdfPKCS7 = signatureUtil.verifySignature(name, BouncyCastleProvider.PROVIDER_NAME);
PdfSignature sig = signatureUtil.getSignature(name);
List<X509Certificate> certificatesToCheck = new ArrayList<>();
certificatesToCheck.add(pdfPKCS7.getSigningCertificate());
while (!certificatesToCheck.isEmpty()) {
X509Certificate certificate = certificatesToCheck.remove(0);
addLtvForChain(certificate, ocspClient, crlClient, getSignatureHashKey(sig));
}
}
outputDss();
}
//
// the actual LTV enabling methods
//
void addLtvForChain(X509Certificate certificate, IOcspClient ocspClient, ICrlClient crlClient, PdfName key) throws GeneralSecurityException, IOException, StreamParsingException, OperatorCreationException, OCSPException {
ValidationData validationData = new ValidationData();
while (certificate != null) {
System.out.println(certificate.getSubjectX500Principal().getName());
X509Certificate issuer = getIssuerCertificate(certificate);
validationData.certs.add(certificate.getEncoded());
byte[] ocspResponse = ocspClient.getEncoded(certificate, issuer, null);
if (ocspResponse != null) {
System.out.println(" with OCSP response");
validationData.ocsps.add(ocspResponse);
X509Certificate ocspSigner = getOcspSignerCertificate(ocspResponse);
if (ocspSigner != null) {
System.out.printf(" signed by %s\n", ocspSigner.getSubjectX500Principal().getName());
}
addLtvForChain(ocspSigner, ocspClient, crlClient, getOcspHashKey(ocspResponse));
} else {
Collection<byte[]> crl = crlClient.getEncoded(certificate, null);
if (crl != null && !crl.isEmpty()) {
System.out.printf(" with %s CRLs\n", crl.size());
validationData.crls.addAll(crl);
for (byte[] crlBytes : crl) {
addLtvForChain(null, ocspClient, crlClient, getCrlHashKey(crlBytes));
}
}
}
certificate = issuer;
}
validated.put(key, validationData);
}
void outputDss() throws IOException {
PdfDictionary dss = new PdfDictionary();
PdfDictionary vrim = new PdfDictionary();
PdfArray ocsps = new PdfArray();
PdfArray crls = new PdfArray();
PdfArray certs = new PdfArray();
PdfCatalog catalog = pdfDocument.getCatalog();
if (pdfDocument.getPdfVersion().compareTo(PdfVersion.PDF_2_0) < 0) {
catalog.addDeveloperExtension(PdfDeveloperExtension.ESIC_1_7_EXTENSIONLEVEL5);
catalog.addDeveloperExtension(new PdfDeveloperExtension(PdfName.ADBE, new PdfName("1.7"), 8));
}
for (PdfName vkey : validated.keySet()) {
PdfArray ocsp = new PdfArray();
PdfArray crl = new PdfArray();
PdfArray cert = new PdfArray();
PdfDictionary vri = new PdfDictionary();
for (byte[] b : validated.get(vkey).crls) {
PdfStream ps = new PdfStream(b);
ps.setCompressionLevel(CompressionConstants.DEFAULT_COMPRESSION);
ps.makeIndirect(pdfDocument);
crl.add(ps);
crls.add(ps);
crls.setModified();
}
for (byte[] b : validated.get(vkey).ocsps) {
b = buildOCSPResponse(b);
PdfStream ps = new PdfStream(b);
ps.setCompressionLevel(CompressionConstants.DEFAULT_COMPRESSION);
ps.makeIndirect(pdfDocument);
ocsp.add(ps);
ocsps.add(ps);
ocsps.setModified();
}
for (byte[] b : validated.get(vkey).certs) {
PdfStream ps = new PdfStream(b);
ps.setCompressionLevel(CompressionConstants.DEFAULT_COMPRESSION);
ps.makeIndirect(pdfDocument);
cert.add(ps);
certs.add(ps);
certs.setModified();
}
if (ocsp.size() > 0) {
ocsp.makeIndirect(pdfDocument);
vri.put(PdfName.OCSP, ocsp);
}
if (crl.size() > 0) {
crl.makeIndirect(pdfDocument);
vri.put(PdfName.CRL, crl);
}
if (cert.size() > 0) {
cert.makeIndirect(pdfDocument);
vri.put(PdfName.Cert, cert);
}
vri.put(PdfName.TU, new PdfDate().getPdfObject());
vri.makeIndirect(pdfDocument);
vrim.put(vkey, vri);
}
vrim.makeIndirect(pdfDocument);
vrim.setModified();
dss.put(PdfName.VRI, vrim);
if (ocsps.size() > 0) {
ocsps.makeIndirect(pdfDocument);
dss.put(PdfName.OCSPs, ocsps);
}
if (crls.size() > 0) {
crls.makeIndirect(pdfDocument);
dss.put(PdfName.CRLs, crls);
}
if (certs.size() > 0) {
certs.makeIndirect(pdfDocument);
dss.put(PdfName.Certs, certs);
}
dss.makeIndirect(pdfDocument);
dss.setModified();
catalog.put(PdfName.DSS, dss);
}
//
// VRI signature hash key calculation
//
static PdfName getCrlHashKey(byte[] crlBytes) throws NoSuchAlgorithmException, IOException, CRLException, CertificateException {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509CRL crl = (X509CRL)cf.generateCRL(new ByteArrayInputStream(crlBytes));
byte[] signatureBytes = crl.getSignature();
DEROctetString octetString = new DEROctetString(signatureBytes);
byte[] octetBytes = octetString.getEncoded();
byte[] octetHash = hashBytesSha1(octetBytes);
PdfName octetName = new PdfName(convertToHex(octetHash));
return octetName;
}
static PdfName getOcspHashKey(byte[] basicResponseBytes) throws NoSuchAlgorithmException, IOException {
BasicOCSPResponse basicResponse = BasicOCSPResponse.getInstance(basicResponseBytes);
byte[] signatureBytes = basicResponse.getSignature().getBytes();
DEROctetString octetString = new DEROctetString(signatureBytes);
byte[] octetBytes = octetString.getEncoded();
byte[] octetHash = hashBytesSha1(octetBytes);
PdfName octetName = new PdfName(convertToHex(octetHash));
return octetName;
}
static PdfName getSignatureHashKey(PdfSignature sig) throws NoSuchAlgorithmException, IOException {
PdfString contents = sig.getContents();
byte[] bc = PdfEncodings.convertToBytes(contents.getValue(), null);
if (PdfName.ETSI_RFC3161.equals(sig.getSubFilter())) {
try ( ASN1InputStream din = new ASN1InputStream(new ByteArrayInputStream(bc)) ) {
ASN1Primitive pkcs = din.readObject();
bc = pkcs.getEncoded();
}
}
byte[] bt = hashBytesSha1(bc);
return new PdfName(convertToHex(bt));
}
static byte[] hashBytesSha1(byte[] b) throws NoSuchAlgorithmException {
MessageDigest sh = MessageDigest.getInstance("SHA1");
return sh.digest(b);
}
static String convertToHex(byte[] bytes) {
ByteBuffer buf = new ByteBuffer();
for (byte b : bytes) {
buf.appendHex(b);
}
return PdfEncodings.convertToString(buf.toByteArray(), null).toUpperCase();
}
//
// OCSP response helpers
//
static X509Certificate getOcspSignerCertificate(byte[] basicResponseBytes) throws CertificateException, OCSPException, OperatorCreationException {
JcaX509CertificateConverter converter = new JcaX509CertificateConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME);
BasicOCSPResponse borRaw = BasicOCSPResponse.getInstance(basicResponseBytes);
BasicOCSPResp bor = new BasicOCSPResp(borRaw);
for (final X509CertificateHolder x509CertificateHolder : bor.getCerts()) {
X509Certificate x509Certificate = converter.getCertificate(x509CertificateHolder);
JcaContentVerifierProviderBuilder jcaContentVerifierProviderBuilder = new JcaContentVerifierProviderBuilder();
jcaContentVerifierProviderBuilder.setProvider(BouncyCastleProvider.PROVIDER_NAME);
final PublicKey publicKey = x509Certificate.getPublicKey();
ContentVerifierProvider contentVerifierProvider = jcaContentVerifierProviderBuilder.build(publicKey);
if (bor.isSignatureValid(contentVerifierProvider))
return x509Certificate;
}
return null;
}
static byte[] buildOCSPResponse(byte[] BasicOCSPResponse) throws IOException {
DEROctetString doctet = new DEROctetString(BasicOCSPResponse);
ASN1EncodableVector v2 = new ASN1EncodableVector();
v2.add(OCSPObjectIdentifiers.id_pkix_ocsp_basic);
v2.add(doctet);
ASN1Enumerated den = new ASN1Enumerated(0);
ASN1EncodableVector v3 = new ASN1EncodableVector();
v3.add(den);
v3.add(new DERTaggedObject(true, 0, new DERSequence(v2)));
DERSequence seq = new DERSequence(v3);
return seq.getEncoded();
}
//
// X509 certificate related helpers
//
static X509Certificate getIssuerCertificate(X509Certificate certificate) throws IOException, StreamParsingException {
String url = getCACURL(certificate);
if (url != null && url.length() > 0) {
HttpURLConnection con = (HttpURLConnection)new URL(url).openConnection();
if (con.getResponseCode() / 100 != 2) {
throw new PdfException(PdfException.InvalidHttpResponse1).setMessageParams(con.getResponseCode());
}
InputStream inp = (InputStream) con.getContent();
X509CertParser parser = new X509CertParser();
parser.engineInit(new ByteArrayInputStream(StreamUtil.inputStreamToArray(inp)));
return (X509Certificate) parser.engineRead();
}
return null;
}
static String getCACURL(X509Certificate certificate) {
ASN1Primitive obj;
try {
obj = getExtensionValue(certificate, Extension.authorityInfoAccess.getId());
if (obj == null) {
return null;
}
ASN1Sequence AccessDescriptions = (ASN1Sequence) obj;
for (int i = 0; i < AccessDescriptions.size(); i++) {
ASN1Sequence AccessDescription = (ASN1Sequence) AccessDescriptions.getObjectAt(i);
if ( AccessDescription.size() != 2 ) {
continue;
}
else if (AccessDescription.getObjectAt(0) instanceof ASN1ObjectIdentifier) {
ASN1ObjectIdentifier id = (ASN1ObjectIdentifier)AccessDescription.getObjectAt(0);
if ("1.3.6.1.5.5.7.48.2".equals(id.getId())) {
ASN1Primitive description = (ASN1Primitive)AccessDescription.getObjectAt(1);
String AccessLocation = getStringFromGeneralName(description);
if (AccessLocation == null) {
return "" ;
}
else {
return AccessLocation ;
}
}
}
}
} catch (IOException e) {
return null;
}
return null;
}
static 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();
}
static String getStringFromGeneralName(ASN1Primitive names) throws IOException {
ASN1TaggedObject taggedObject = (ASN1TaggedObject) names ;
return new String(ASN1OctetString.getInstance(taggedObject, false).getOctets(), "ISO-8859-1");
}
//
// inner class
//
static class ValidationData {
final List<byte[]> crls = new ArrayList<byte[]>();
final List<byte[]> ocsps = new ArrayList<byte[]>();
final List<byte[]> certs = new ArrayList<byte[]>();
}
//
// member variables
//
final PdfDocument pdfDocument;
final Map<PdfName,ValidationData> validated = new HashMap<PdfName,ValidationData>();
}
(AdobeLtvEnabling.java)
Example use
You can use the AdobeLtvEnabling class like this:
try ( PdfReader pdfReader = new PdfReader(SOURCE);
PdfWriter pdfWriter = new PdfWriter(TARGET);
PdfDocument pdfDocument = new PdfDocument(pdfReader, pdfWriter,
new StampingProperties().preserveEncryption().useAppendMode())) {
AdobeLtvEnabling adobeLtvEnabling = new AdobeLtvEnabling(pdfDocument);
IOcspClient ocsp = new OcspClientBouncyCastle(null);
ICrlClient crl = new CrlClientOnline();
adobeLtvEnabling.enable(ocsp, crl);
}
(MakeLtvEnabled test testLtvEnableSignWithoutLtv)
Limitations
As this code essentially is ported from the iText 5 code from the referenced answer, it also inherits the limitations listed in that answer:
The code works under some simplifying restrictions, in particular:
signature time stamps are ignored,
retrieved CRLs are assumed to be direct and complete,
the complete certificate chains are assumed to be buildable using AIA entries.
You can improve the code accordingly if these restrictions are not acceptable for you.

How to get Keystore fingerprint from code

I am currently struggling with getting some security to the Unity3d app I'm working on, and I want to add verification that apk file wasn't tampered with by some patchers. I know how to get keystore fingerprint from a built app (like keytool), but I have a hard time figuring out how to get that fingerprint from the code of my app during runtime to check that it is the same. I've gone through a lot of other threads to no success so far (like this: Get certificate fingerprint from android app)
Has anyone found solution how to do this or hint where I should start looking? Thanks in advance!
Modify the getCertificateSHA1Fingerprint function from the answer you linked to take Android Context as parameter. Get the Context from Unity and send it to this function then mark as static.
Java:
public final class CertificateSHA1Fingerprint
{
private static String getCertificateSHA1Fingerprint(Context mContext)
{
PackageManager pm = mContext.getPackageManager();
String packageName = mContext.getPackageName();
int flags = PackageManager.GET_SIGNATURES;
PackageInfo packageInfo = null;
try {
packageInfo = pm.getPackageInfo(packageName, flags);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
Signature[] signatures = packageInfo.signatures;
byte[] cert = signatures[0].toByteArray();
InputStream input = new ByteArrayInputStream(cert);
CertificateFactory cf = null;
try {
cf = CertificateFactory.getInstance("X509");
} catch (CertificateException e) {
e.printStackTrace();
}
X509Certificate c = null;
try {
c = (X509Certificate) cf.generateCertificate(input);
} catch (CertificateException e) {
e.printStackTrace();
}
String hexString = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA1");
byte[] publicKey = md.digest(c.getEncoded());
hexString = byte2HexFormatted(publicKey);
} catch (NoSuchAlgorithmException e1) {
e1.printStackTrace();
} catch (CertificateEncodingException e) {
e.printStackTrace();
}
return hexString;
}
public static String byte2HexFormatted(byte[] arr)
{
StringBuilder str = new StringBuilder(arr.length * 2);
for (int i = 0; i < arr.length; i++)
{
String h = Integer.toHexString(arr[i]);
int l = h.length();
if (l == 1) h = "0" + h;
if (l > 2) h = h.substring(l - 2, l);
str.append(h.toUpperCase());
if (i < (arr.length - 1)) str.append(':');
}
return str.toString();
}
}
C#:
AndroidJavaClass unityClass;
AndroidJavaObject unityActivity;
AndroidJavaObject unityContext;
AndroidJavaClass customClass;
public string getCertificateSHA1Fingerprint()
{
//Replace with your full package name
string packageName = "com.example.CertificateSHA1Fingerprint";
unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
unityActivity = unityClass.GetStatic<AndroidJavaObject>("currentActivity");
unityContext = unityActivity.Call<AndroidJavaObject>("getApplicationContext");
customClass = new AndroidJavaClass(packageName);
string result = customClass.CallStatic<string>("getCertificateSHA1Fingerprint", unityContext);
return result;
}
You only have to build the Java function with Android Studio and convert it into Jar or .AAR file then put it in your <ProjectName>Assets\Plugins\Android folder. The C# code will be able to communicate with it.

Trying to use the certificate to connect in a web server

I ve been trying to use two different certificates to communicate in a web server( Web server 1). When I use the first one, I can communicate with the web server without any problem. But when I try to use the second one, I have some problems: Even if I change the certificate and make another conection with the web server, it returns the information that a had used in the first certificate.
When I close and open the tomcat 8, I can use the second one, but I can't use the first one again.
I´ve been using more than one certificate , and using the same method in another web server(Web server 2) without problem.
Follow the code bellow:
public String sendXml(String xmlCabecalho, String xmlEnvNFse) throws ExceptionServicoAbrasf {
try {
SignXml signXml = new SignXml(this.keyStoreService.getKeystore(), this.keyStoreService.getAliasCert(), this.keyStoreService.getPasswordPfx());
xmlEnvNFse = signXml.signAndSend(xmlEnvNFse);
loadInfoCertificate();
return executarServicoEnvioNFse(xmlCabecalho, xmlEnvNFse);
} catch (Exception ex) {
throw new ExceptionServicoAbrasf("Failure to sing. " + ex.getMessage());
}
}
//add xml to sign
public String signAndSend(String xml) throws Exception {
//sign
return sign(xml, "InfDeclaracaoPrestacaoServico", "Rps");
}
//sign
private String sign(String xml, String tag, String tagParentSignature) throws Exception {
Document document = documentFactory(xml);
XMLSignatureFactory signatureFactory = XMLSignatureFactory
.getInstance("DOM");
ArrayList<Transform> transformList = signatureFactory(signatureFactory);
loadCertificates(signatureFactory);
NodeList elements = document.getElementsByTagName(tag);
org.w3c.dom.Element el = (org.w3c.dom.Element) elements.item(0);
el.setIdAttribute("Id", true);
String id = el.getAttribute("Id");
Reference ref = signatureFactory.newReference("#" + id,
signatureFactory.newDigestMethod(DigestMethod.SHA1, null),
transformList, null, null);
SignedInfo si = signatureFactory.newSignedInfo(signatureFactory
.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,
(C14NMethodParameterSpec) null), signatureFactory
.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
Collections.singletonList(ref));
XMLSignature signature = signatureFactory.newXMLSignature(si, keyInfo);
DOMSignContext dsc = new DOMSignContext(privateKey, document.getElementsByTagName(tagParentSignature).item(0));
signature.sign(dsc);
return outputXML(document);
}
//load certificate
protected void loadCertificates(XMLSignatureFactory signatureFactory) throws Exception {
if (keyStore != null) {
KeyStore.PrivateKeyEntry pkEntry = null;
if (keyStore.isKeyEntry(alias)) {
char[] pin = (password == null ? "" : password).toCharArray();
pkEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias,
new KeyStore.PasswordProtection(pin));
privateKey = pkEntry.getPrivateKey();
X509Certificate cert = (X509Certificate) pkEntry.getCertificate();
KeyInfoFactory keyInfoFactory = signatureFactory.getKeyInfoFactory();
List<X509Certificate> x509Content = new ArrayList<>();
x509Content.add(cert);
X509Data x509Data = keyInfoFactory.newX509Data(x509Content);
keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(x509Data));
} else {
throw new Exception("Alias invalid.");
}
} else {
throw new Exception("Invalid Certificate Information.");
}
}
///normalize xml
protected String outputXML(Document doc) throws TransformerException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
trans.transform(new DOMSource(doc), new StreamResult(os));
String xml = os.toString();
if ((xml != null) && (!"".equals(xml))) {
xml = xml.replaceAll("\\r\\n", "");
xml = xml.replaceAll(" standalone=\"no\"", "");
}
return xml;
}
//load info certificate
private void loadInfoCertificate() {
System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");
System.clearProperty("javax.net.ssl.keyStore");
System.clearProperty("javax.net.ssl.keyStorePassword");
System.clearProperty("javax.net.ssl.trustStore");
System.setProperty("javax.net.ssl.keyStore", this.keyStoreService.getPathPfx());
System.setProperty("javax.net.ssl.keyStorePassword", this.keyStoreService.getPasswordPfx());
System.setProperty("javax.net.ssl.trustStoreType", "JKS");
System.setProperty("javax.net.ssl.trustStore", this.pathCacerts);
}
//send web service
private String executarServicoEnvioNFse(String xmlCabecalho, String xmlCorpo) throws ExceptionServicoAbrasf {
Input input = new Input(xmlCabecalho, xmlCorpo);
Output output = generateReturn(input);
return output.getOutputXML();
}
//generate conection web service
private Output generateReturn(ws.Input parameters) throws ExceptionServicoAbrasf {
ws.Nfse port = loadNfseDivPort();
return port.generateReturn(parameters);
}
//return web service
private ws.Nfse loadNfseDivPort() throws ExceptionServicoAbrasf {
try {
String urlStr = "https://homolog.govdigital.com.br/ws/div?wsdl";
URL url = new URL(urlStr);
ws.NfseServiceImplDivService service = new ws.NfseServiceImplDivService(url);
ws.Nfse port = service.getNfseDivPort();
return port;
} catch (MalformedURLException ex) {
throw new ExceptionServicoAbrasf("Invalid url. " + ex.getMessage());
}
}

Java Bouncy Castle OCSP Url

I am using bouncy castle 1.48 to verify certificate validation with OCSP. It works good.
But I'm using Ocsp Url as static variable and I want to read it from certificate. Url is written in certificate as Authority Info Access
[1]Authority Info Access
Access Method=On-line Certificate Status Protocol (1.3.6.1.5.5.7.48.1)
Alternative Name:
URL=http://ocsp.mydomain
I got org.bouncycastle.asn1.x509.AuthorityInformationAccess object from certificate
byte[] octetBytes = certificate.getExtensionValue(X509Extension.authorityInfoAccess.getId());
ASN1InputStream octetStream = new ASN1InputStream(octetBytes);
byte[] encoded = X509ExtensionUtil.fromExtensionValue(octetBytes).getEncoded();
ASN1Sequence seq = ASN1Sequence.getInstance(ASN1Primitive.fromByteArray(encoded));
AuthorityInformationAccess access = AuthorityInformationAccess.getInstance(seq);
which writes AuthorityInformationAccess: Oid(1.3.6.1.5.5.7.48.1) but cant get Url from there
I found the way.
private String getOcspUrl(X509Certificate certificate) throws Exception {
byte[] octetBytes = certificate
.getExtensionValue(X509Extension.authorityInfoAccess.getId());
DLSequence dlSequence = null;
ASN1Encodable asn1Encodable = null;
try {
ASN1Primitive fromExtensionValue = X509ExtensionUtil
.fromExtensionValue(octetBytes);
if (!(fromExtensionValue instanceof DLSequence))
return null;
dlSequence = (DLSequence) fromExtensionValue;
for (int i = 0; i < dlSequence.size(); i++) {
asn1Encodable = dlSequence.getObjectAt(i);
if (asn1Encodable instanceof DLSequence)
break;
}
if (!(asn1Encodable instanceof DLSequence))
return null;
dlSequence = (DLSequence) asn1Encodable;
for (int i = 0; i < dlSequence.size(); i++) {
asn1Encodable = dlSequence.getObjectAt(i);
if (asn1Encodable instanceof DERTaggedObject)
break;
}
if (!(asn1Encodable instanceof DERTaggedObject))
return null;
DERTaggedObject derTaggedObject = (DERTaggedObject) asn1Encodable;
byte[] encoded = derTaggedObject.getEncoded();
if (derTaggedObject.getTagNo() == 6) {
int len = encoded[1];
return new String(encoded, 2, len);
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
This is how I did it:
private String getOcspUrlFromCertificate(X509Certificate cert) {
byte[] extensionValue = cert.getExtensionValue(X509Extensions.AuthorityInfoAccess.getId());
try {
ASN1Sequence asn1Seq = (ASN1Sequence) X509ExtensionUtil.fromExtensionValue(extensionValue); // AuthorityInfoAccessSyntax
Enumeration<?> objects = asn1Seq.getObjects();
while (objects.hasMoreElements()) {
ASN1Sequence obj = (ASN1Sequence) objects.nextElement(); // AccessDescription
DERObjectIdentifier oid = (DERObjectIdentifier) obj.getObjectAt(0); // accessMethod
DERTaggedObject location = (DERTaggedObject) obj.getObjectAt(1); // accessLocation
if (location.getTagNo() == GeneralName.uniformResourceIdentifier) {
DEROctetString uri = (DEROctetString) location.getObject();
String str = new String(uri.getOctets());
if (oid.equals(X509ObjectIdentifiers.id_ad_ocsp)) {
return str;
}
}
}
} catch (Exception e) {
logger.error("Error", e);
}
return null;
}
Use BouncyCastle X509CertificateHolder.
Using BouncyCastle 1.66, Java 8, and Lombok val...
public static String getOcspUrl(final String certPEM) {
val certHolder = toCertificateHolder(certPEM);
val aiaExtension = AuthorityInformationAccess.fromExtensions(certHolder.getExtensions());
val ocspUrl = Arrays.stream(aiaExtension.getAccessDescriptions())
.filter(ad -> ad.getAccessMethod().equals(X509ObjectIdentifiers.id_ad_ocsp))
.map(ad -> ad.getAccessLocation().getName().toASN1Primitive().toString())
.findFirst();
return ocspUrl.get();
}
public static X509CertificateHolder toCertificateHolder(final String certPEM) {
val parser = new PEMParser(new StringReader(certPEM));
return (X509CertificateHolder) parser.readObject();
}
With BouncyCastle 1.9 is:
Dependences
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.59</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.59</version>
</dependency>
Method for get url OCSP
private 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();
}
public String getOcspUrl() throws Exception {
ASN1Primitive obj;
try {
obj = getExtensionValue(getFirstCertificate(), Extension.authorityInfoAccess.getId());
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
if (obj == null) {
return null;
}
AuthorityInformationAccess authorityInformationAccess = AuthorityInformationAccess.getInstance(obj);
AccessDescription[] accessDescriptions = authorityInformationAccess.getAccessDescriptions();
for (AccessDescription accessDescription : accessDescriptions) {
boolean correctAccessMethod = accessDescription.getAccessMethod().equals(X509ObjectIdentifiers.ocspAccessMethod);
if (!correctAccessMethod) {
continue;
}
GeneralName name = accessDescription.getAccessLocation();
if (name.getTagNo() != GeneralName.uniformResourceIdentifier) {
continue;
}
DERIA5String derStr = DERIA5String.getInstance((ASN1TaggedObject) name.toASN1Primitive(), false);
return derStr.getString();
}
return null;
}
Function to verif revocation
public CertificateStatus verifRevocationWithOCSP(X509Certificate certificate,X509Certificate issuerCertificate) throws Exception{
OcspClientBouncyCastle ocspClient = new OcspClientBouncyCastle();
String urlOCSP = getOcspUrl();
BasicOCSPResp basicOCSPResp = ocspClient.getBasicOCSPResp(certificate, issuerCertificate, urlOCSP);
if (basicOCSPResp == null)
throw new IOException("Error en la consulta ar servidor OCSP ["+urlOCSP+"]");
BasicOCSPResp basicResponse = basicOCSPResp;
SingleResp[] responses = basicResponse.getResponses();
if (responses.length == 1) {
SingleResp resp = responses[0];
Object status = resp.getCertStatus();
System.out.println("OBJECT: "+status);
if (status == CertificateStatus.GOOD) {
return CertificateStatus.GOOD;
} else if (status instanceof RevokedStatus) {
RevokedStatus revokedStatus = (RevokedStatus)status;
return revokedStatus;
} else if(status instanceof UnknownStatus){
UnknownStatus unknownStatus = (UnknownStatus)status;
return unknownStatus;
}
throw new IOException("Tipo de respuesta de OCSP ["+status+"] desconocido");
}
else
throw new IOException("No se recibio ni una respuesta al consultar el OCSP para la URL ["+urlOCSP+"]");
}

Categories