EidasMetadataService { byte[] generate(EidasSigner signer) throws CertificateEncodingException, IOException, MarshallingException, SignatureException, TransformerFactoryConfigurationError, TransformerException { EntityDescriptor entityDescriptor = new EntityDescriptorBuilder().buildObject(); entityDescriptor.setID(id); entityDescriptor.setEntityID(entityId); entityDescriptor.setValidUntil(new DateTime(validUntil.getTime())); IDPSSODescriptor idpDescriptor = new IDPSSODescriptorBuilder().buildObject(); idpDescriptor.setWantAuthnRequestsSigned(true); idpDescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS); KeyDescriptor kd = new KeyDescriptorBuilder().buildObject(); kd.setUse(UsageType.SIGNING); KeyInfo ki = new KeyInfoBuilder().buildObject(); X509Data x509 = new X509DataBuilder().buildObject(); org.opensaml.xmlsec.signature.X509Certificate x509Cert = new X509CertificateBuilder().buildObject(); x509Cert.setValue(new String(Base64.getEncoder().encode(sigCert.getEncoded()), StandardCharsets.UTF_8)); x509.getX509Certificates().add(x509Cert); ki.getX509Datas().add(x509); kd.setKeyInfo(ki); idpDescriptor.getKeyDescriptors().add(kd); kd = new KeyDescriptorBuilder().buildObject(); kd.setUse(UsageType.ENCRYPTION); ki = new KeyInfoBuilder().buildObject(); x509 = new X509DataBuilder().buildObject(); x509Cert = new X509CertificateBuilder().buildObject(); x509Cert.setValue(new String(Base64.getEncoder().encode(encCert.getEncoded()), StandardCharsets.UTF_8)); x509.getX509Certificates().add(x509Cert); ki.getX509Datas().add(x509); kd.setKeyInfo(ki); EncryptionMethod encMethod = new EncryptionMethodBuilder().buildObject(); encMethod.setAlgorithm(EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256_GCM); kd.getEncryptionMethods().add(encMethod); idpDescriptor.getKeyDescriptors().add(kd); SingleSignOnService sso = new SingleSignOnServiceBuilder().buildObject(); sso.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); sso.setLocation(postEndpoint); idpDescriptor.getSingleSignOnServices().add(sso); sso = new SingleSignOnServiceBuilder().buildObject(); sso.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); sso.setLocation(redirectEndpoint); idpDescriptor.getSingleSignOnServices().add(sso); for ( EidasNameIdType nameIDType : this.supportedNameIdTypes ) { NameIDFormat nif = new NameIDFormatBuilder().buildObject(); nif.setFormat(nameIDType.value); idpDescriptor.getNameIDFormats().add(nif); } for ( EidasPersonAttributes att : attributes ) { Attribute a = new AttributeBuilder().buildObject(); a.setFriendlyName(att.getFriendlyName()); a.setName(att.getValue()); idpDescriptor.getAttributes().add(a); } entityDescriptor.getRoleDescriptors().add(idpDescriptor); Organization organization = new OrganizationBuilder().buildObject(); OrganizationDisplayName odn = new OrganizationDisplayNameBuilder().buildObject(); odn.setValue(organisation.getDisplayName()); odn.setXMLLang(organisation.getLangId()); organization.getDisplayNames().add(odn); OrganizationName on = new OrganizationNameBuilder().buildObject(); on.setValue(organisation.getName()); on.setXMLLang(organisation.getLangId()); organization.getOrganizationNames().add(on); OrganizationURL ourl = new OrganizationURLBuilder().buildObject(); ourl.setValue(organisation.getUrl()); ourl.setXMLLang(organisation.getLangId()); organization.getURLs().add(ourl); entityDescriptor.setOrganization(organization); ContactPerson cp = new ContactPersonBuilder().buildObject(); Company comp = new CompanyBuilder().buildObject(); comp.setName(technicalContact.getCompany()); cp.setCompany(comp); GivenName gn = new GivenNameBuilder().buildObject(); gn.setName(technicalContact.getGivenName()); cp.setGivenName(gn); SurName sn = new SurNameBuilder().buildObject(); sn.setName(technicalContact.getSurName()); cp.setSurName(sn); EmailAddress email = new EmailAddressBuilder().buildObject(); email.setAddress(technicalContact.getEmail()); cp.getEmailAddresses().add(email); TelephoneNumber tel = new TelephoneNumberBuilder().buildObject(); tel.setNumber(technicalContact.getTel()); cp.getTelephoneNumbers().add(tel); cp.setType(ContactPersonTypeEnumeration.TECHNICAL); entityDescriptor.getContactPersons().add(cp); cp = new ContactPersonBuilder().buildObject(); comp = new CompanyBuilder().buildObject(); comp.setName(supportContact.getCompany()); cp.setCompany(comp); gn = new GivenNameBuilder().buildObject(); gn.setName(supportContact.getGivenName()); cp.setGivenName(gn); sn = new SurNameBuilder().buildObject(); sn.setName(supportContact.getSurName()); cp.setSurName(sn); email = new EmailAddressBuilder().buildObject(); email.setAddress(supportContact.getEmail()); cp.getEmailAddresses().add(email); tel = new TelephoneNumberBuilder().buildObject(); tel.setNumber(supportContact.getTel()); cp.getTelephoneNumbers().add(tel); cp.setType(ContactPersonTypeEnumeration.SUPPORT); entityDescriptor.getContactPersons().add(cp); EntityAttributes entAttr = new EntityAttributesBuilder().buildObject(EntityAttributes.DEFAULT_ELEMENT_NAME); Namespace assertion = new Namespace(SAMLConstants.SAML20_NS, SAMLConstants.SAML20_PREFIX); entAttr.getNamespaceManager().registerNamespaceDeclaration(assertion); Attribute attr = new AttributeBuilder().buildObject(); attr.setName("urn:oasis:names:tc:SAML:attribute:assurance-certification"); attr.setNameFormat(Attribute.URI_REFERENCE); XSAny any = new XSAnyBuilder().buildObject(AttributeValue.DEFAULT_ELEMENT_NAME); any.setTextContent("http: attr.getAttributeValues().add(any); entAttr.getAttributes().add(attr); Attribute protocolAttribute = new AttributeBuilder().buildObject(); protocolAttribute.setName(PROTOCOL_VERSION_URI); protocolAttribute.setNameFormat(Attribute.URI_REFERENCE); XSAny protocolVersion = new XSAnyBuilder().buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, new QName("xs:string")); protocolVersion.setTextContent(SUPPORTED_PROTOCOL_VERSION); protocolAttribute.getAttributeValues().add(protocolVersion); entAttr.getAttributes().add(protocolAttribute); Attribute appliccationIdentifier = new AttributeBuilder().buildObject(); appliccationIdentifier.setName(APPLICATION_IDENTIFIER_URI); appliccationIdentifier.setNameFormat(Attribute.URI_REFERENCE); XSAny applicationIdentifierVersion = new XSAnyBuilder().buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, new QName("xs:string")); applicationIdentifierVersion.setTextContent("German eIDAS Middleware version: " + middlewareVersion); appliccationIdentifier.getAttributeValues().add(applicationIdentifierVersion); entAttr.getAttributes().add(appliccationIdentifier); if (requesterIdFlag) { Attribute requesterIdAttribute = new AttributeBuilder().buildObject(); requesterIdAttribute.setName("http: requesterIdAttribute.setNameFormat(Attribute.URI_REFERENCE); XSAny requesterIdValue = new XSAnyBuilder().buildObject(AttributeValue.DEFAULT_ELEMENT_NAME); requesterIdValue.setTextContent("http: requesterIdAttribute.getAttributeValues().add(requesterIdValue); entAttr.getAttributes().add(requesterIdAttribute); } Extensions ext = new ExtensionsBuilder().buildObject(); ext.getUnknownXMLObjects().add(entAttr); DigestMethod dm = new DigestMethodBuilder().buildObject(); dm.setAlgorithm(MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA256); ext.getUnknownXMLObjects().add(dm); SigningMethod sm = new SigningMethodBuilder().buildObject(); sm.setAlgorithm(XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA256); sm.setMinKeySize(256); ext.getUnknownXMLObjects().add(sm); sm = new SigningMethodBuilder().buildObject(); sm.setAlgorithm(EidasSigner.DIGEST_NONSPEC.equals(signer.getSigDigestAlg()) ? XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256 : XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256_MGF1); sm.setMinKeySize(3072); sm.setMaxKeySize(4096); ext.getUnknownXMLObjects().add(sm); entityDescriptor.setExtensions(ext); List<Signature> sigs = new ArrayList<>(); if (doSign) { XMLSignatureHandler.addSignature(entityDescriptor, signer.getSigKey(), signer.getSigCert(), signer.getSigType(), signer.getSigDigestAlg()); sigs.add(entityDescriptor.getSignature()); } EntityDescriptorMarshaller arm = new EntityDescriptorMarshaller(); Element all = arm.marshall(entityDescriptor); if (!sigs.isEmpty()) { Signer.signObjects(sigs); } Transformer trans = Utils.getTransformer(); trans.setOutputProperty(OutputKeys.ENCODING, StandardCharsets.UTF_8.name()); byte[] result = null; try (ByteArrayOutputStream bout = new ByteArrayOutputStream()) { trans.transform(new DOMSource(all), new StreamResult(bout)); result = bout.toByteArray(); } return result; } EidasMetadataService(String id,
                       String entityId,
                       Date validUntil,
                       X509Certificate sigCert,
                       X509Certificate encCert,
                       EidasOrganisation organisation,
                       EidasContactPerson technicalContact,
                       EidasContactPerson supportContact,
                       String postEndpoint,
                       String redirectEndpoint,
                       List<EidasPersonAttributes> attributes,
                       List<EidasNameIdType> supportedNameIdTypes,
                       String middlewareVersion,
                       boolean doSign,
                       boolean requesterIdFlag);   }
@Test void createMetadataWithApplicationIdentifier() throws Exception { EidasMetadataService metadataService = getEidasMetadataService(); EidasSigner signer = new EidasSigner(keyPair.getKey(), keyPair.getCert()); byte[] metadataByteArray = metadataService.generate(signer); String metadataString = new String(metadataByteArray, StandardCharsets.UTF_8); Assertions.assertTrue(metadataString.contains("http: Assertions.assertTrue(metadataString.contains("German eIDAS Middleware version: 2.0")); Assertions.assertTrue(metadataString.contains("http: }
@Test void validateMetadataWithWrongCredentialsThrowsSignatureException() throws Exception { EidasMetadataService eidasMetadataService = getEidasMetadataService(); EidasSigner signer = new EidasSigner(keyPair.getKey(), keyPair.getCert()); byte[] metadataByteArray = eidasMetadataService.generate(signer); EntityDescriptor entityDescriptor = getEntityDescriptor(metadataByteArray); SAMLSignatureProfileValidator samlSignatureProfileValidator = new SAMLSignatureProfileValidator(); samlSignatureProfileValidator.validate(entityDescriptor.getSignature()); X509Certificate x509Certificate = Utils.readCert(EidasMetadataServiceTest.class.getResourceAsStream("/WrongSignerCert.cer")); Signature sig = entityDescriptor.getSignature(); BasicCredential bc = new BasicX509Credential(x509Certificate); Assertions.assertThrows(SignatureException.class, () -> SignatureValidator.validate(sig, bc)); }
@Test void validateUnsignedMetadataThrowsSignatureException() throws Exception { EidasMetadataService eidasMetadataService = getEidasMetadataService(false); EidasSigner signer = new EidasSigner(keyPair.getKey(), keyPair.getCert()); byte[] metadataByteArray = eidasMetadataService.generate(signer); EntityDescriptor entityDescriptor = getEntityDescriptor(metadataByteArray); Signature sig = entityDescriptor.getSignature(); Credential credential = new BasicX509Credential(keyPair.getCert()); Assertions.assertThrows(ConstraintViolationException.class, () -> SignatureValidator.validate(sig, credential)); }
@Test void manipulatedMetadataThrowsSignatureException() throws Exception { EidasMetadataService eidasMetadataService = getEidasMetadataService(); EidasSigner signer = new EidasSigner(keyPair.getKey(), keyPair.getCert()); byte[] metadataByteArray = eidasMetadataService.generate(signer); String metadataString = new String(metadataByteArray); String manipulatedString = metadataString.replace("entityID", "newEntityID"); byte[] manipulatedStringBytes = manipulatedString.getBytes(StandardCharsets.UTF_8); EntityDescriptor entityDescriptor = getEntityDescriptor(manipulatedStringBytes); SAMLSignatureProfileValidator samlSignatureProfileValidator = new SAMLSignatureProfileValidator(); samlSignatureProfileValidator.validate(entityDescriptor.getSignature()); Credential credential = new BasicX509Credential(keyPair.getCert()); Signature sig = entityDescriptor.getSignature(); Assertions.assertThrows(SignatureException.class, () -> SignatureValidator.validate(sig, credential)); }
@Test void validateMetadataSignature() throws Exception { EidasMetadataService metadataService = getEidasMetadataService(); EidasSigner signer = new EidasSigner(keyPair.getKey(), keyPair.getCert()); byte[] metadataByteArray = metadataService.generate(signer); EntityDescriptor metadata = getEntityDescriptor(metadataByteArray); SAMLSignatureProfileValidator samlSignatureProfileValidator = new SAMLSignatureProfileValidator(); samlSignatureProfileValidator.validate(metadata.getSignature()); Credential credential = new BasicX509Credential(keyPair.getCert()); SignatureValidator.validate(metadata.getSignature(), credential); }