@Test public void testVerify() { ReceiptVerifier r = new ReceiptVerifier(new Local("src/test/resources/receipt"), "ch.sudo.cyberduck", "4.7.3"); assertTrue(r.verify(new DisabledLicenseVerifierCallback())); assertEquals("b8e85600dffe", r.getGuid()); }
@Override public boolean verify(final LicenseVerifierCallback callback) { try { final CMSSignedData s = new CMSSignedData(new FileInputStream(file.getAbsolute())); Store certs = s.getCertificates(); SignerInformationStore signers = s.getSignerInfos(); for(SignerInformation signer : signers.getSigners()) { final Collection<X509CertificateHolder> matches = certs.getMatches(signer.getSID()); for(X509CertificateHolder holder : matches) { if(!signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider( new BouncyCastleProvider() ).build(holder))) { return false; } } } final CMSProcessable signedContent = s.getSignedContent(); byte[] originalContent = (byte[]) signedContent.getContent(); final ASN1Primitive asn = ASN1Primitive.fromByteArray(originalContent); byte[] opaque = null; String bundleIdentifier = null; String bundleVersion = null; byte[] hash = null; if(asn instanceof ASN1Set) { final ASN1Set set = (ASN1Set) asn; final Enumeration enumeration = set.getObjects(); while(enumeration.hasMoreElements()) { Object next = enumeration.nextElement(); if(next instanceof DLSequence) { DLSequence sequence = (DLSequence) next; ASN1Encodable type = sequence.getObjectAt(0); if(type instanceof ASN1Integer) { if(((ASN1Integer) type).getValue().intValue() == 2) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { bundleIdentifier = new String(((DEROctetString) value).getOctets(), StandardCharsets.UTF_8); } } else if(((ASN1Integer) type).getValue().intValue() == 3) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { bundleVersion = new String(((DEROctetString) value).getOctets(), StandardCharsets.UTF_8); } } else if(((ASN1Integer) type).getValue().intValue() == 4) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { opaque = ((DEROctetString) value).getOctets(); } } else if(((ASN1Integer) type).getValue().intValue() == 5) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { hash = ((DEROctetString) value).getOctets(); } } } } } } else { log.error(String.format("Expected set of attributes for %s", asn)); return false; } if(!StringUtils.equals(application, StringUtils.trim(bundleIdentifier))) { log.error(String.format("Bundle identifier %s in ASN set does not match", bundleIdentifier)); return false; } if(!StringUtils.equals(version, StringUtils.trim(bundleVersion))) { log.warn(String.format("Bundle version %s in ASN set does not match", bundleVersion)); } final NetworkInterface en0 = NetworkInterface.getByName("en0"); if(null == en0) { log.warn("No network interface en0"); return true; } else { final byte[] mac = en0.getHardwareAddress(); if(null == mac) { log.error("Cannot determine MAC address"); return true; } final String hex = Hex.encodeHexString(mac); if(log.isDebugEnabled()) { log.debug(String.format("Interface en0 %s", hex)); } final MessageDigest digest = MessageDigest.getInstance("SHA-1"); digest.update(mac); if(null == opaque) { log.error(String.format("Missing opaque string in ASN.1 set %s", asn)); return false; } digest.update(opaque); if(null == bundleIdentifier) { log.error(String.format("Missing bundle identifier in ASN.1 set %s", asn)); return false; } digest.update(bundleIdentifier.getBytes(StandardCharsets.UTF_8)); final byte[] result = digest.digest(); if(Arrays.equals(result, hash)) { if(log.isInfoEnabled()) { log.info(String.format("Valid receipt for GUID %s", hex)); } guid = hex; return true; } else { log.error(String.format("Failed verification. Hash with GUID %s does not match hash in receipt", hex)); return false; } } } catch(IOException | GeneralSecurityException | CMSException | SecurityException e) { log.error("Receipt validation error", e); return false; } catch(Exception e) { log.error("Unknown receipt validation error", e); return true; } }
ReceiptVerifier implements LicenseVerifier { @Override public boolean verify(final LicenseVerifierCallback callback) { try { final CMSSignedData s = new CMSSignedData(new FileInputStream(file.getAbsolute())); Store certs = s.getCertificates(); SignerInformationStore signers = s.getSignerInfos(); for(SignerInformation signer : signers.getSigners()) { final Collection<X509CertificateHolder> matches = certs.getMatches(signer.getSID()); for(X509CertificateHolder holder : matches) { if(!signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider( new BouncyCastleProvider() ).build(holder))) { return false; } } } final CMSProcessable signedContent = s.getSignedContent(); byte[] originalContent = (byte[]) signedContent.getContent(); final ASN1Primitive asn = ASN1Primitive.fromByteArray(originalContent); byte[] opaque = null; String bundleIdentifier = null; String bundleVersion = null; byte[] hash = null; if(asn instanceof ASN1Set) { final ASN1Set set = (ASN1Set) asn; final Enumeration enumeration = set.getObjects(); while(enumeration.hasMoreElements()) { Object next = enumeration.nextElement(); if(next instanceof DLSequence) { DLSequence sequence = (DLSequence) next; ASN1Encodable type = sequence.getObjectAt(0); if(type instanceof ASN1Integer) { if(((ASN1Integer) type).getValue().intValue() == 2) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { bundleIdentifier = new String(((DEROctetString) value).getOctets(), StandardCharsets.UTF_8); } } else if(((ASN1Integer) type).getValue().intValue() == 3) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { bundleVersion = new String(((DEROctetString) value).getOctets(), StandardCharsets.UTF_8); } } else if(((ASN1Integer) type).getValue().intValue() == 4) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { opaque = ((DEROctetString) value).getOctets(); } } else if(((ASN1Integer) type).getValue().intValue() == 5) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { hash = ((DEROctetString) value).getOctets(); } } } } } } else { log.error(String.format("Expected set of attributes for %s", asn)); return false; } if(!StringUtils.equals(application, StringUtils.trim(bundleIdentifier))) { log.error(String.format("Bundle identifier %s in ASN set does not match", bundleIdentifier)); return false; } if(!StringUtils.equals(version, StringUtils.trim(bundleVersion))) { log.warn(String.format("Bundle version %s in ASN set does not match", bundleVersion)); } final NetworkInterface en0 = NetworkInterface.getByName("en0"); if(null == en0) { log.warn("No network interface en0"); return true; } else { final byte[] mac = en0.getHardwareAddress(); if(null == mac) { log.error("Cannot determine MAC address"); return true; } final String hex = Hex.encodeHexString(mac); if(log.isDebugEnabled()) { log.debug(String.format("Interface en0 %s", hex)); } final MessageDigest digest = MessageDigest.getInstance("SHA-1"); digest.update(mac); if(null == opaque) { log.error(String.format("Missing opaque string in ASN.1 set %s", asn)); return false; } digest.update(opaque); if(null == bundleIdentifier) { log.error(String.format("Missing bundle identifier in ASN.1 set %s", asn)); return false; } digest.update(bundleIdentifier.getBytes(StandardCharsets.UTF_8)); final byte[] result = digest.digest(); if(Arrays.equals(result, hash)) { if(log.isInfoEnabled()) { log.info(String.format("Valid receipt for GUID %s", hex)); } guid = hex; return true; } else { log.error(String.format("Failed verification. Hash with GUID %s does not match hash in receipt", hex)); return false; } } } catch(IOException | GeneralSecurityException | CMSException | SecurityException e) { log.error("Receipt validation error", e); return false; } catch(Exception e) { log.error("Unknown receipt validation error", e); return true; } } }
ReceiptVerifier implements LicenseVerifier { @Override public boolean verify(final LicenseVerifierCallback callback) { try { final CMSSignedData s = new CMSSignedData(new FileInputStream(file.getAbsolute())); Store certs = s.getCertificates(); SignerInformationStore signers = s.getSignerInfos(); for(SignerInformation signer : signers.getSigners()) { final Collection<X509CertificateHolder> matches = certs.getMatches(signer.getSID()); for(X509CertificateHolder holder : matches) { if(!signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider( new BouncyCastleProvider() ).build(holder))) { return false; } } } final CMSProcessable signedContent = s.getSignedContent(); byte[] originalContent = (byte[]) signedContent.getContent(); final ASN1Primitive asn = ASN1Primitive.fromByteArray(originalContent); byte[] opaque = null; String bundleIdentifier = null; String bundleVersion = null; byte[] hash = null; if(asn instanceof ASN1Set) { final ASN1Set set = (ASN1Set) asn; final Enumeration enumeration = set.getObjects(); while(enumeration.hasMoreElements()) { Object next = enumeration.nextElement(); if(next instanceof DLSequence) { DLSequence sequence = (DLSequence) next; ASN1Encodable type = sequence.getObjectAt(0); if(type instanceof ASN1Integer) { if(((ASN1Integer) type).getValue().intValue() == 2) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { bundleIdentifier = new String(((DEROctetString) value).getOctets(), StandardCharsets.UTF_8); } } else if(((ASN1Integer) type).getValue().intValue() == 3) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { bundleVersion = new String(((DEROctetString) value).getOctets(), StandardCharsets.UTF_8); } } else if(((ASN1Integer) type).getValue().intValue() == 4) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { opaque = ((DEROctetString) value).getOctets(); } } else if(((ASN1Integer) type).getValue().intValue() == 5) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { hash = ((DEROctetString) value).getOctets(); } } } } } } else { log.error(String.format("Expected set of attributes for %s", asn)); return false; } if(!StringUtils.equals(application, StringUtils.trim(bundleIdentifier))) { log.error(String.format("Bundle identifier %s in ASN set does not match", bundleIdentifier)); return false; } if(!StringUtils.equals(version, StringUtils.trim(bundleVersion))) { log.warn(String.format("Bundle version %s in ASN set does not match", bundleVersion)); } final NetworkInterface en0 = NetworkInterface.getByName("en0"); if(null == en0) { log.warn("No network interface en0"); return true; } else { final byte[] mac = en0.getHardwareAddress(); if(null == mac) { log.error("Cannot determine MAC address"); return true; } final String hex = Hex.encodeHexString(mac); if(log.isDebugEnabled()) { log.debug(String.format("Interface en0 %s", hex)); } final MessageDigest digest = MessageDigest.getInstance("SHA-1"); digest.update(mac); if(null == opaque) { log.error(String.format("Missing opaque string in ASN.1 set %s", asn)); return false; } digest.update(opaque); if(null == bundleIdentifier) { log.error(String.format("Missing bundle identifier in ASN.1 set %s", asn)); return false; } digest.update(bundleIdentifier.getBytes(StandardCharsets.UTF_8)); final byte[] result = digest.digest(); if(Arrays.equals(result, hash)) { if(log.isInfoEnabled()) { log.info(String.format("Valid receipt for GUID %s", hex)); } guid = hex; return true; } else { log.error(String.format("Failed verification. Hash with GUID %s does not match hash in receipt", hex)); return false; } } } catch(IOException | GeneralSecurityException | CMSException | SecurityException e) { log.error("Receipt validation error", e); return false; } catch(Exception e) { log.error("Unknown receipt validation error", e); return true; } } ReceiptVerifier(final Local file);  ReceiptVerifier(final Local file, final String application, final String version); }
ReceiptVerifier implements LicenseVerifier { @Override public boolean verify(final LicenseVerifierCallback callback) { try { final CMSSignedData s = new CMSSignedData(new FileInputStream(file.getAbsolute())); Store certs = s.getCertificates(); SignerInformationStore signers = s.getSignerInfos(); for(SignerInformation signer : signers.getSigners()) { final Collection<X509CertificateHolder> matches = certs.getMatches(signer.getSID()); for(X509CertificateHolder holder : matches) { if(!signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider( new BouncyCastleProvider() ).build(holder))) { return false; } } } final CMSProcessable signedContent = s.getSignedContent(); byte[] originalContent = (byte[]) signedContent.getContent(); final ASN1Primitive asn = ASN1Primitive.fromByteArray(originalContent); byte[] opaque = null; String bundleIdentifier = null; String bundleVersion = null; byte[] hash = null; if(asn instanceof ASN1Set) { final ASN1Set set = (ASN1Set) asn; final Enumeration enumeration = set.getObjects(); while(enumeration.hasMoreElements()) { Object next = enumeration.nextElement(); if(next instanceof DLSequence) { DLSequence sequence = (DLSequence) next; ASN1Encodable type = sequence.getObjectAt(0); if(type instanceof ASN1Integer) { if(((ASN1Integer) type).getValue().intValue() == 2) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { bundleIdentifier = new String(((DEROctetString) value).getOctets(), StandardCharsets.UTF_8); } } else if(((ASN1Integer) type).getValue().intValue() == 3) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { bundleVersion = new String(((DEROctetString) value).getOctets(), StandardCharsets.UTF_8); } } else if(((ASN1Integer) type).getValue().intValue() == 4) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { opaque = ((DEROctetString) value).getOctets(); } } else if(((ASN1Integer) type).getValue().intValue() == 5) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { hash = ((DEROctetString) value).getOctets(); } } } } } } else { log.error(String.format("Expected set of attributes for %s", asn)); return false; } if(!StringUtils.equals(application, StringUtils.trim(bundleIdentifier))) { log.error(String.format("Bundle identifier %s in ASN set does not match", bundleIdentifier)); return false; } if(!StringUtils.equals(version, StringUtils.trim(bundleVersion))) { log.warn(String.format("Bundle version %s in ASN set does not match", bundleVersion)); } final NetworkInterface en0 = NetworkInterface.getByName("en0"); if(null == en0) { log.warn("No network interface en0"); return true; } else { final byte[] mac = en0.getHardwareAddress(); if(null == mac) { log.error("Cannot determine MAC address"); return true; } final String hex = Hex.encodeHexString(mac); if(log.isDebugEnabled()) { log.debug(String.format("Interface en0 %s", hex)); } final MessageDigest digest = MessageDigest.getInstance("SHA-1"); digest.update(mac); if(null == opaque) { log.error(String.format("Missing opaque string in ASN.1 set %s", asn)); return false; } digest.update(opaque); if(null == bundleIdentifier) { log.error(String.format("Missing bundle identifier in ASN.1 set %s", asn)); return false; } digest.update(bundleIdentifier.getBytes(StandardCharsets.UTF_8)); final byte[] result = digest.digest(); if(Arrays.equals(result, hash)) { if(log.isInfoEnabled()) { log.info(String.format("Valid receipt for GUID %s", hex)); } guid = hex; return true; } else { log.error(String.format("Failed verification. Hash with GUID %s does not match hash in receipt", hex)); return false; } } } catch(IOException | GeneralSecurityException | CMSException | SecurityException e) { log.error("Receipt validation error", e); return false; } catch(Exception e) { log.error("Unknown receipt validation error", e); return true; } } ReceiptVerifier(final Local file);  ReceiptVerifier(final Local file, final String application, final String version); @Override boolean verify(final LicenseVerifierCallback callback); String getGuid(); }
ReceiptVerifier implements LicenseVerifier { @Override public boolean verify(final LicenseVerifierCallback callback) { try { final CMSSignedData s = new CMSSignedData(new FileInputStream(file.getAbsolute())); Store certs = s.getCertificates(); SignerInformationStore signers = s.getSignerInfos(); for(SignerInformation signer : signers.getSigners()) { final Collection<X509CertificateHolder> matches = certs.getMatches(signer.getSID()); for(X509CertificateHolder holder : matches) { if(!signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider( new BouncyCastleProvider() ).build(holder))) { return false; } } } final CMSProcessable signedContent = s.getSignedContent(); byte[] originalContent = (byte[]) signedContent.getContent(); final ASN1Primitive asn = ASN1Primitive.fromByteArray(originalContent); byte[] opaque = null; String bundleIdentifier = null; String bundleVersion = null; byte[] hash = null; if(asn instanceof ASN1Set) { final ASN1Set set = (ASN1Set) asn; final Enumeration enumeration = set.getObjects(); while(enumeration.hasMoreElements()) { Object next = enumeration.nextElement(); if(next instanceof DLSequence) { DLSequence sequence = (DLSequence) next; ASN1Encodable type = sequence.getObjectAt(0); if(type instanceof ASN1Integer) { if(((ASN1Integer) type).getValue().intValue() == 2) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { bundleIdentifier = new String(((DEROctetString) value).getOctets(), StandardCharsets.UTF_8); } } else if(((ASN1Integer) type).getValue().intValue() == 3) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { bundleVersion = new String(((DEROctetString) value).getOctets(), StandardCharsets.UTF_8); } } else if(((ASN1Integer) type).getValue().intValue() == 4) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { opaque = ((DEROctetString) value).getOctets(); } } else if(((ASN1Integer) type).getValue().intValue() == 5) { final ASN1Encodable value = sequence.getObjectAt(2); if(value instanceof DEROctetString) { hash = ((DEROctetString) value).getOctets(); } } } } } } else { log.error(String.format("Expected set of attributes for %s", asn)); return false; } if(!StringUtils.equals(application, StringUtils.trim(bundleIdentifier))) { log.error(String.format("Bundle identifier %s in ASN set does not match", bundleIdentifier)); return false; } if(!StringUtils.equals(version, StringUtils.trim(bundleVersion))) { log.warn(String.format("Bundle version %s in ASN set does not match", bundleVersion)); } final NetworkInterface en0 = NetworkInterface.getByName("en0"); if(null == en0) { log.warn("No network interface en0"); return true; } else { final byte[] mac = en0.getHardwareAddress(); if(null == mac) { log.error("Cannot determine MAC address"); return true; } final String hex = Hex.encodeHexString(mac); if(log.isDebugEnabled()) { log.debug(String.format("Interface en0 %s", hex)); } final MessageDigest digest = MessageDigest.getInstance("SHA-1"); digest.update(mac); if(null == opaque) { log.error(String.format("Missing opaque string in ASN.1 set %s", asn)); return false; } digest.update(opaque); if(null == bundleIdentifier) { log.error(String.format("Missing bundle identifier in ASN.1 set %s", asn)); return false; } digest.update(bundleIdentifier.getBytes(StandardCharsets.UTF_8)); final byte[] result = digest.digest(); if(Arrays.equals(result, hash)) { if(log.isInfoEnabled()) { log.info(String.format("Valid receipt for GUID %s", hex)); } guid = hex; return true; } else { log.error(String.format("Failed verification. Hash with GUID %s does not match hash in receipt", hex)); return false; } } } catch(IOException | GeneralSecurityException | CMSException | SecurityException e) { log.error("Receipt validation error", e); return false; } catch(Exception e) { log.error("Unknown receipt validation error", e); return true; } } ReceiptVerifier(final Local file);  ReceiptVerifier(final Local file, final String application, final String version); @Override boolean verify(final LicenseVerifierCallback callback); String getGuid();  }