CGI-SE-Trusted-Services / c2c-common

http://pvendil.github.io/c2c-common/
GNU Affero General Public License v3.0
45 stars 18 forks source link

= Java Implementation of ITS Intelligent Transport Systems (ITS) Security header and certificate formats

This is a library used to generate data structures from the ETSI TS 103 097 v1.3.1, ETSI TS 102 941 v1.3.1 (EU) and IEEE 1609.2 2016 (With 1609.2a 2017 Amendment) (US) specification.

== License

The software is released under AGPL, link:LICENSE.txt[] for more details. In order to get the software under a different licensing agreement please contact p.vendil (at) cgi.com

== Changelog

=== 2.0.0-Beta5

=== 2.0.0-Beta4

=== 2.0.0-Beta3

=== 2.0.0-Beta2

=== 2.0.0-Beta1

=== 0.9.8

=== 0.9.7

=== 0.9.6

=== 0.9.5

=== 0.9.0

== EU Standard ETSI TS 103 097 V1.3.1

It supports generation of the following data structures will all related substructures:

See Javadoc and examples below for more detailed information.

=== Example Code

Full example code can be seen in src/test/java/org/certificateservices/custom/c2x/demo it contains demo of both ETSI (EU) and IEEE (US) standards.

Before doing anything else you need to initialize a CryptoManager used for all cryptographic operations.

[source, java]

    //Create a crypto manager in charge of communicating with underlying cryptographic components
    CryptoManager cryptoManager = new DefaultCryptoManager();   
    // Initialize the crypto manager to use soft keys using the bouncy castle cryptographic provider.
    cryptoManager.setupAndConnect(new DefaultCryptoManagerParams("BC"));

==== Root CA

Example code on how to generate Root a CA, use the AuthorityCertGenerator:

[source, java]

    // Create an authority certificate generator and initialize it with the crypto manager. 
    ETSIAuthorityCertGenerator authorityCertGenerator = new ETSIAuthorityCertGenerator(cryptoManager);

    // Generate a reference to the Root CA Keys     
    KeyPair rootCASigningKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);
    KeyPair rootCAEncryptionKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);

    ValidityPeriod rootCAValidityPeriod = new ValidityPeriod(new Date(), DurationChoices.years, 45);
    List<Integer> countries = new ArrayList<Integer>();
    countries.add(SWEDEN);
    GeographicRegion region = GeographicRegion.generateRegionForCountrys(countries);

    // Generate the root CA Certificate, without any encryption keys or geographic region.
    EtsiTs103097Certificate rootCACertificate = authorityCertGenerator.genRootCA("testrootca.test.com", // caName
            rootCAValidityPeriod, //ValidityPeriod
            region, //GeographicRegion
            3, // minChainDepth
            -1, // chainDepthRange
            Hex.decode("0138"), // cTLServiceSpecificPermissions, 2 octets
            SignatureChoices.ecdsaNistP256Signature, //signingPublicKeyAlgorithm
            rootCASigningKeys.getPublic(), // signPublicKey
            rootCASigningKeys.getPrivate(), // signPrivateKey
            SymmAlgorithm.aes128Ccm, // symmAlgorithm
            BasePublicEncryptionKeyChoices.ecdsaNistP256,  // encPublicKeyAlgorithm
            rootCAEncryptionKeys.getPublic()); // encPublicKey
    // There also exists a more general root ca generation method giving more flexibility in parameters.

==== Enrollment CA

To generate an Enrollment CA:

[source, java]

    // Generate a reference to the Enrollment CA Keys       
    KeyPair enrollmentCASigningKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);
    KeyPair enrollmentCAEncryptionKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);

    ValidityPeriod enrollmentCAValidityPeriod = new ValidityPeriod(new Date(), DurationChoices.years, 37);

    // Generate a reference to the Enrollment CA Signing Keys
    EtsiTs103097Certificate enrollmentCACertificate =authorityCertGenerator.genEnrollmentCA("testea.test.com", // CA Name
            enrollmentCAValidityPeriod, 
            region,  //GeographicRegion
            new SubjectAssurance(1,3), // subject assurance (optional)
            SignatureChoices.ecdsaNistP256Signature, //signingPublicKeyAlgorithm
            enrollmentCASigningKeys.getPublic(), // signPublicKey, i.e public key in certificate
            rootCACertificate, // signerCertificate
            rootCASigningKeys.getPublic(), // signCertificatePublicKey, must be specified separately to support implicit certificates.
            rootCASigningKeys.getPrivate(),
            SymmAlgorithm.aes128Ccm, // symmAlgorithm
            BasePublicEncryptionKeyChoices.ecdsaNistP256,  // encPublicKeyAlgorithm
            enrollmentCAEncryptionKeys.getPublic() // encryption public key
            );

==== Authority CA

To generate an Authority CA:

[source, java]

    // Generate a reference to the Authorization CA Keys        
    KeyPair authorityCASigningKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);
    KeyPair authorityCAEncryptionKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);

    ValidityPeriod authorityCAValidityPeriod = new ValidityPeriod(new Date(), DurationChoices.years, 15);

    // Generate a reference to the Authorization CA Signing Keys
    EtsiTs103097Certificate authorityCACertificate = authorityCertGenerator.genAuthorizationCA(
            "testaa.test.com", // CA Name
            authorityCAValidityPeriod, 
            region,  //GeographicRegion
            new SubjectAssurance(1,3), // subject assurance (optional)
            SignatureChoices.ecdsaNistP256Signature, //signingPublicKeyAlgorithm
            authorityCASigningKeys.getPublic(), // signPublicKey, i.e public key in certificate
            rootCACertificate, // signerCertificate
            rootCASigningKeys.getPublic(), // signCertificatePublicKey,
            rootCASigningKeys.getPrivate(),
            SymmAlgorithm.aes128Ccm, // symmAlgorithm
            BasePublicEncryptionKeyChoices.ecdsaNistP256,  // encPublicKeyAlgorithm
            authorityCAEncryptionKeys.getPublic() // encryption public key
            );

==== Enrollment Credential

To create an Enrollment Credential use the EnrollmentCredentialCertGenerator.

[source, java]

    // First we create a Enrollment Credential Cert Generator using the newly created Enrollment CA.
    ETSIEnrollmentCredentialGenerator enrollmentCredentialCertGenerator = new ETSIEnrollmentCredentialGenerator(cryptoManager);
    // Next we generate keys for an enrollment credential.
    KeyPair enrollmentCredentialSigningKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);
    // Next we generate keys for an enrollment credential.
    KeyPair enrollmentCredentialEncryptionKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);

    ValidityPeriod enrollCertValidityPeriod = new ValidityPeriod(new Date(), DurationChoices.years, 35);

    // Then use the following command to generate a enrollment credential
    EtsiTs103097Certificate enrollmentCredential = enrollmentCredentialCertGenerator.genEnrollCredential(
            "0102030405060708", // unique identifier name
            enrollCertValidityPeriod, 
            region,
            Hex.decode("01C0"), //SSP data set in SecuredCertificateRequestService appPermission, two byte, for example: 0x01C0
            3, // assuranceLevel
            7, // confidenceLevel
            SignatureChoices.ecdsaNistP256Signature, //signingPublicKeyAlgorithm
            enrollmentCredentialSigningKeys.getPublic(), // signPublicKey, i.e public key in certificate
            enrollmentCACertificate, // signerCertificate
            enrollmentCASigningKeys.getPublic(), // signCertificatePublicKey,
            enrollmentCASigningKeys.getPrivate(), 
            SymmAlgorithm.aes128Ccm, // symmAlgorithm 
            BasePublicEncryptionKeyChoices.ecdsaNistP256, // encPublicKeyAlgorithm
            enrollmentCredentialEncryptionKeys.getPublic() // encryption public key
            );

    // There also exists a more general method with flexible app permissions.

==== Authorization Ticket

To create an Authorization Ticket l use the AuthorizationTicketCertGenerator.

[source, java]

    // Authorization tickets are created by the ETSIAuthorizationTicketGenerator
    ETSIAuthorizationTicketGenerator authorizationCertGenerator = new ETSIAuthorizationTicketGenerator(cryptoManager);

    // Next we generate keys for an authorization certificate.
    KeyPair authorizationTokenSigningKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);

    // Next we generate keys for an authorization certificate.
    KeyPair authorizationTicketEncryptionKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);

    ValidityPeriod authorizationCertValidityPeriod = new ValidityPeriod(new Date(), DurationChoices.years, 35);

    PsidSsp[] appPermissions = new PsidSsp[1];
    appPermissions[0] = new PsidSsp(new Psid(6), null); // Insert proper app permissions here.

    // Generate a certificate as an explicit certificate.
    EtsiTs103097Certificate authorizationCert = authorizationCertGenerator.genAuthorizationTicket(
            authorizationCertValidityPeriod, // Validity Period
            region, // region,
            new SubjectAssurance(1,3), // Subject Assurance, optional
            appPermissions,
            SignatureChoices.ecdsaNistP256Signature, //signingPublicKeyAlgorithm
            authorizationTokenSigningKeys.getPublic(), // signPublicKey, i.e public key in certificate
            authorityCACertificate, // signerCertificate
            authorityCASigningKeys.getPublic(), // signCertificatePublicKey,
            authorityCASigningKeys.getPrivate(), 
            SymmAlgorithm.aes128Ccm, // symmAlgorithm 
            BasePublicEncryptionKeyChoices.ecdsaNistP256, // encPublicKeyAlgorithm
            authorizationTicketEncryptionKeys.getPublic() // encryption public key
            );

==== Trust List Manager Certificate

To create a trust list manager certificate.

[source, java]

    // Generate a reference to the Root CA Keys
    KeyPair tlmSigningKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);
    KeyPair tlmEncryptionKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);

    ValidityPeriod tlmValidityPeriod = new ValidityPeriod(new Date(), DurationChoices.years, 45);
    // Generate the root CA Certificate, without any encryption keys or geographic region.
    EtsiTs103097Certificate trustListManagerCertificate = authorityCertGenerator.genTrustListManagerCert(
            "testtlm.test.com", // name
            rootCAValidityPeriod, //ValidityPeriod
            region, //GeographicRegion, optional
            Hex.decode("01C8"), // cTLServiceSpecificPermissions, 2 octets
            SignatureChoices.ecdsaNistP256Signature, //signingPublicKeyAlgorithm
            rootCASigningKeys.getPublic(), // signPublicKey
            rootCASigningKeys.getPrivate() // signPrivateKey
             );
    // There also exists a more general root ca generation method giving more flexibility in parameters.

==== Secured Messages

To create Secured Messages such as CAM or DENM use the SecuredMessageGenerator.

[source, java]

            // EtsiTs103097Data are created by the Secure Message Generator
            ETSISecuredDataGenerator securedMessageGenerator = new ETSISecuredDataGenerator(ETSISecuredDataGenerator.DEFAULT_VERSION, cryptoManager, HashAlgorithm.sha256, SignatureChoices.ecdsaNistP256Signature);

            // To generate a Signed CA Message it is possible to use
            List<HashedId3> hashedId3s = new ArrayList<HashedId3>();
            hashedId3s.add(new HashedId3(cryptoManager.digest(rootCACertificate.getEncoded(),HashAlgorithm.sha256)));
            hashedId3s.add(new HashedId3(cryptoManager.digest(enrollmentCACertificate.getEncoded(),HashAlgorithm.sha256)));
            SequenceOfHashedId3 inlineP2pcdRequest = new SequenceOfHashedId3(hashedId3s);

            byte[] cAMessageData = Hex.decode("SomeCAMessage");
            EtsiTs103097DataSigned cAMessage = securedMessageGenerator.genCAMessage(new Time64(new Date()), // generationTime
                    inlineP2pcdRequest, //  InlineP2pcdRequest (Required)
                    rootCACertificate, // requestedCertificate
                    cAMessageData, // inner opaque CA message data
                    SecuredDataGenerator.SignerIdentifierType.SIGNER_CERTIFICATE, // signerIdentifierType
                    authorizationCert, // signerCertificate
                    authorizationTokenSigningKeys.getPrivate()); // signerPrivateKey

            // To generate a Signed DEN Message
            byte[] dENMessageData = Hex.decode("SomeDENMessage");
            EtsiTs103097DataSigned dENMessage = securedMessageGenerator.genDENMessage(
                    new Time64(new Date()), // generationTime
                    new ThreeDLocation(1,2,3), // generationLocation
                    dENMessageData, // inner opaque DEN message data
                    authorizationCert, // signerCertificate
                    authorizationTokenSigningKeys.getPrivate()); // signerPrivateKey

            // The securedMessageGenerator also have methods to generate more general EtsiTs103097Data profiles such as
            // EtsiTs103097DataSigned, EtsiTs103097DataSignedExternalPayload, EtsiTs103097DataEncrypted and
            // EtsiTs103097DataSignedAndEncrypted.

            // It is then possible to create a signed message with the following code
              // First generate a Header with
            HeaderInfo hi = securedMessageGenerator.genHeaderInfo(
                    123L, // psid Required,
                    null, // generationTime Optional
                    null, // expiryTime Optional
                    null, // generationLocation Optional
                    null, // p2pcdLearningRequest Optional
                    null, // cracaid Optional
                    null, // crlSeries Optional
                    null, // encType Type of encryption when encrypting a message with a encryption key references in a signed message instead of a certificate. Optional
                    null, // encryptionKey Optional
                    null, // inlineP2pcdRequest Optional
            null // requestedCertificate Optional
                    );

            // This method can be used to sign the data
            EtsiTs103097DataSigned signedData = securedMessageGenerator.genEtsiTs103097DataSigned(hi,
                    "TestData".getBytes(), // The actual payload message to sign.
                    SecuredDataGenerator.SignerIdentifierType.HASH_ONLY, // One of  HASH_ONLY, SIGNER_CERTIFICATE, CERT_CHAIN indicating reference data of the signer to include in the message
                    new EtsiTs103097Certificate[] {authorizationCert,authorityCACertificate, rootCACertificate}, // The chain is required even though it isn't included in
                      // the message if eventual implicit certificates need to have it's public key reconstructed.
                    authorizationTokenSigningKeys.getPrivate()); // Signing Key
            // It is also possible to generate a EtsiTs103097DataSignedExternalPayload with the genEtsiTs103097DataSignedExternalPayload()
            // method.

            // The message can be encrypted with the method
              // First construct a list of recipient which have the public key specified either as a symmetric key, certificate or in header of signed data
              // In this example we will use certificate as reciever, see package org.certificateservices.custom.c2x.ieee1609dot2.generator.recipient for more details.
            EtsiTs103097DataEncrypted encryptedData = securedMessageGenerator.genEtsiTs103097DataEncrypted(BasePublicEncryptionKeyChoices.ecdsaNistP256,
                      signedData.getEncoded(), new Recipient[] {new CertificateRecipient(enrollmentCredential)});

            // It is also possible to sign and encrypt in one go.
            EtsiTs103097DataEncrypted encryptedAndSignedMessage = securedMessageGenerator.genEtsiTs103097DataSignedAndEncrypted(hi,
                    "TestData2".getBytes(),
                    SecuredDataGenerator.SignerIdentifierType.HASH_ONLY,
                    new EtsiTs103097Certificate[] {authorizationCert,authorityCACertificate, rootCACertificate},
                    authorizationTokenSigningKeys.getPrivate(), // Important to use the reconstructed private key for implicit certificates
                    BasePublicEncryptionKeyChoices.ecdsaNistP256,
                    new Recipient[] {new CertificateRecipient(enrollmentCredential)});

            // To decrypt and verify a signed message it is possible to use the following
              // First build a truststore of trust anchors (root CA certificate or equivalent)
            Map<HashedId8, Certificate> trustStore = securedMessageGenerator.buildCertStore(new EtsiTs103097Certificate[] {rootCACertificate});
              // Second build a store of known certificate that might be referenced in the message.
            Map<HashedId8, Certificate> certStore = securedMessageGenerator.buildCertStore(new EtsiTs103097Certificate[] {authorizationCert, authorityCACertificate});
              // To decrypt build a reciever store of known decryption keys and related receiver info, this can be certificate, signed message containing encryption key
              // in header, symmetric key or pre shared key.
            Map<HashedId8, Receiver> recieverStore = securedMessageGenerator.buildRecieverStore(new Receiver[] { new CertificateReciever(enrollmentCredentialEncryptionKeys.getPrivate(), enrollmentCredential)});
              // Finally perform the decryption and verification of siganture with.
            DecryptAndVerifyResult decryptAndVerifyResult = securedMessageGenerator.decryptAndVerifySignedData(encryptedAndSignedMessage.getEncoded(),
                    certStore,
                    trustStore,
                    recieverStore,
                    true, //requiredSignature true if message must be signed otherwise a IllegalArgument is throwm
                    true //requireEncryption true if message must be encrypted otherwise a IllegalArgument is throwm
                    );
               // The decryptAndVerifyResult contains the inner opaque data, the related header info and signer identifier
               // if related message was signed.

              // It is also possible to use the methods decryptData or verifySignedData (or verifyReferencedSignedData) for alternative methods to verify and decrypt messages.

==== To Encode and Decode Certificates and Secured Messages

[source, java]

    // To encode a certificate to a byte array use the following method
    byte[] certificateData = authorizationCert.getEncoded();

    // To decode certificate data use the following constructor
    EtsiTs103097Certificate decodedCertificate = new EtsiTs103097Certificate(certificateData);

    // To decode message data use the following constructor.
    EtsiTs103097Data decodedMessage = new EtsiTs103097Data(messageData);
    // If the message profile is known there also exists EtsiTs103097DataSigned, EtsiTs103097DataSignedExternalPayload,
    // EtsiTs103097DataEncrypted classes that performs validation according to each profile.

== EU Standard ETSI TS 102 941 V1.3.1

It supports generation of the following data structures will all related substructures:

See Javadoc and examples below for more detailed information.

=== Example Code

Full example code can be seen in src/test/java/org/certificateservices/custom/c2x/demo. The example code assumes you have access to a generated PKI according to ETSI TS 103 097 standard.

Before generating any CA Message create a CA Message generator with:

[source, java]

    // Create a ETSITS102941MessagesCaGenerator generator
    messagesCaGenerator = new ETSITS102941MessagesCaGenerator(Ieee1609Dot2Data.DEFAULT_VERSION,
            cryptoManager, // The initialized crypto manager to use.
            HashAlgorithm.sha256, // digest algorithm to use.
            Signature.SignatureChoices.ecdsaNistP256Signature,  // define which signature scheme to use.
            false); // If EC points should be represented as uncompressed.

==== EnrolRequestMessage

To create an EnrolRequestMessage use the following code.

[source, java]

    // First create the InnerEcRequest object
    InnerEcRequest initialInnerEcRequest = genDummyInnerEcRequest(enrolCredSignKeys.getPublic());
    EtsiTs103097DataEncryptedUnicast initialEnrolRequestMessage = messagesCaGenerator.genInitialEnrolmentRequestMessage(
            new Time64(new Date()), // generation Time
            initialInnerEcRequest,
            enrolCredSignKeys.getPublic(),enrolCredSignKeys.getPrivate(), // The key pair used in the enrolment credential used for self signed PoP
            enrolmentCACert); // The EA certificate to encrypt message to.

    // All messages can be encoded to byte[] using
    byte[] encodedMessage = initialEnrolRequestMessage.getEncoded();

    // To parse and encoded message create a new instance of related EtsiTs103097Data profile.
    EtsiTs103097DataEncryptedUnicast decodedMessage = new EtsiTs103097DataEncryptedUnicast(encodedMessage);

    // To Create an rekey EnrolRequestMessage use the following code.

    // Use a separate method when performing rekey that contains signature of previous message.
    InnerEcRequest reKeyInnerEcRequest = genDummyInnerEcRequest(enrolCredReSignKeys.getPublic());
    EtsiTs103097DataEncryptedUnicast rekeyEnrolRequestMessage = messagesCaGenerator.genRekeyEnrolmentRequestMessage(
            new Time64(new Date()), // generation Time
            reKeyInnerEcRequest, // Inner EC Request containing PublicKeys with new keys.
            enrollmentCredCertChain, // The certificate chain of the current (old) enrolment credential.
            enrolCredSignKeys.getPrivate(), // Private key if current (old) enrolment credential.
            enrolCredReSignKeys.getPublic(),enrolCredReSignKeys.getPrivate(), // The key pair used in the enrolment credential used for self signed PoP
            enrolmentCACert); // The EA certificate to encrypt message to.

To verify a EnrolRequestMessage use:

[source, java]

    // First build a certificate store and a trust store to verify signature.
    // These can be null if only initial messages are used.
    Map<HashedId8, Certificate> enrolCredCertStore = messagesCaGenerator.buildCertStore(enrollmentCredCertChain);
    Map<HashedId8, Certificate> trustStore = messagesCaGenerator.buildCertStore(new EtsiTs103097Certificate[]{rootCACert});

    // Then create a receiver store to decrypt the message
    Map<HashedId8, Receiver> enrolCAReceipients = messagesCaGenerator.buildRecieverStore(new Receiver[] {new CertificateReciever(enrolCAEncKeys.getPrivate(),enrolmentCACert)});
    // Then decrypt and verify with:
    // Important: this method only verifies the signature, it does not validate header information.
    RequestVerifyResult<InnerEcRequest> enrolmentRequestResult = messagesCaGenerator.decryptAndVerifyEnrolmentRequestMessage(rekeyEnrolRequestMessage,enrolCredCertStore,trustStore,enrolCAReceipients);
    // The verify result for enrolment request returns a special value object containing both inner message and
    // requestHash used in response.

    // The result object of all verify message method contains the following information:
    enrolmentRequestResult.getSignerIdentifier(); // The identifier of the signer
    enrolmentRequestResult.getHeaderInfo(); // The header information of the signer of the message
    enrolmentRequestResult.getValue(); // The inner message that was signed and or encrypted.
    enrolmentRequestResult.getSecretKey(); // The symmetrical key used in Ecies request operations and is set when verifying all
    // request messages. The secret key should usually be used to encrypt the response back to the requester.

==== EnrolResponseMessage

To generate and verify EnrolResponseMessage

[source, java]

    // First generate a InnerECResponse
    InnerEcResponse innerEcResponse = new InnerEcResponse(enrolmentRequestResult.getRequestHash(), EnrollmentResponseCode.ok,enrolmentCredCert);
    // Then generate the EnrolmentResponseMessage with:
    EtsiTs103097DataEncryptedUnicast enrolResponseMessage = messagesCaGenerator.genEnrolmentResponseMessage(
            new Time64(new Date()), // generation Time
            innerEcResponse,
            enrollmentCAChain, // Chain of EA used to sign message
            enrolCASignKeys.getPrivate(),
            SymmAlgorithm.aes128Ccm, // Encryption algorithm used
            enrolmentRequestResult.getSecretKey()); // Use symmetric key from the verification result when verifying the request.

    // To verify EnrolResponseMessage use:
    // Build certstore
    Map<HashedId8, Certificate> enrolCACertStore = messagesCaGenerator.buildCertStore(enrollmentCAChain);

    // Build reciever store containing the symmetric key used in the request.
    Map<HashedId8, Receiver> enrolCredSharedKeyReceivers = messagesCaGenerator.buildRecieverStore(new Receiver[] {new PreSharedKeyReceiver(enrolmentRequestResult.getSecretKey())});
    VerifyResult<InnerEcResponse> enrolmentResponseResult = messagesCaGenerator.decryptAndVerifyEnrolmentResponseMessage(
            enrolResponseMessage,
            enrolCACertStore, // Certificate chain if EA CA
            trustStore,
            enrolCredSharedKeyReceivers
    );

==== AuthorizationRequestMessage

To generate and verify AuthorizationRequestMessage

[source, java]

    // To generate an AuthorizationRequestMessage it is possible to generate
    // the message with and without POP and privacy set. This example generates
    // message with POP and privacy.

    // First generate a PublicKeys, hmacKey and SharedAtRequest structures
    PublicKeys publicKeys = messagesCaGenerator.genPublicKeys(signAlg,authTicketSignKeys.getPublic(),SymmAlgorithm.aes128Ccm,encAlg, authTicketEncKeys.getPublic());
    byte[] hmacKey = genHmacKey();
    SharedAtRequest sharedAtRequest = genDummySharedAtRequest(publicKeys, hmacKey);

    EtsiTs103097DataEncryptedUnicast authRequestMessage = messagesCaGenerator.genAuthorizationRequestMessage(
            new Time64(new Date()), // generation Time
            publicKeys,
            hmacKey,
            sharedAtRequest,
            enrollmentCredCertChain, // Certificate chain of enrolment credential to sign outer message to AA
            enrolCredSignKeys.getPrivate(), // Private key used to sign message.
            authTicketSignKeys.getPublic(), //The public key of the auth ticket, used to create POP, null if no POP should be generated.
            authTicketSignKeys.getPrivate(), // The private key of the auth ticket, used to create POP, null if no POP should be generated.
            authorizationCACert, // The AA certificate to encrypt outer message to.
            enrolmentCACert, // Encrypt inner ecSignature with given certificate, required if withPrivacy is true.
            true // Encrypt the inner ecSignature message sent to EA
    );

     // To verify an AuthorizationRequest use the following code.

     // Build a recipient store for Authorization Authority
    Map<HashedId8, Receiver> authorizationCAReceipients = messagesCaGenerator.buildRecieverStore(new Receiver[] {new CertificateReciever(authorizationCAEncKeys.getPrivate(),authorizationCACert)});

    // To decrypt the message and verify the external POP signature (not the inner eCSignature signed for EA CA).
    RequestVerifyResult<InnerAtRequest> authRequestResult = messagesCaGenerator.decryptAndVerifyAuthorizationRequestMessage(authRequestMessage,
             true, // Expect AuthorizationRequestPOP content
             authorizationCAReceipients); // Receivers able to decrypt the message
    // The AuthorizationRequestData contains the innerAtRequest and calculated requestHash
    InnerAtRequest innerAtRequest = authRequestResult.getValue();
    // There exists another method to decrypt (if privacy is used) and verify inner ecSignature with:
    VerifyResult<EcSignature> ecSignatureVerifyResult = messagesCaGenerator.decryptAndVerifyECSignature(innerAtRequest.getEcSignature(),
            innerAtRequest.getSharedAtRequest(),
            true,
            enrolCredCertStore, // Certificate store to verify the signing enrollment credential
            trustStore,
            enrolCAReceipients); // the EA certificate used to decrypt the inner message.

    // The verified and decrypted (if withPrivacy) eCSignature is retrived with
    EcSignature ecSignature = ecSignatureVerifyResult.getValue();

==== AuthorizationResponseMessage

To generate and verify AuthorizationResponseMessage

[source, java]

    // First create innerAtResponse
    InnerAtResponse innerAtResponse = new InnerAtResponse(authRequestResult.getRequestHash(),
            AuthorizationResponseCode.ok,
            authTicketCert);
    EtsiTs103097DataEncryptedUnicast authResponseMessage = messagesCaGenerator.genAuthorizationResponseMessage(
            new Time64(new Date()), // generation Time
            innerAtResponse,
            authorizationCAChain, // The AA certificate chain signing the message
            authorizationCASignKeys.getPrivate(),
            SymmAlgorithm.aes128Ccm, // Encryption algorithm used.
            authRequestResult.getSecretKey()); // The symmetric key generated in the request.

    // To verify AuthorizationResponse use:

    // Build reciever store containing the symmetric key used in the request.
    Map<HashedId8, Receiver> authTicketSharedKeyReceivers = messagesCaGenerator.buildRecieverStore(new Receiver[] {new PreSharedKeyReceiver(authRequestResult.getSecretKey())});
    Map<HashedId8, Certificate> authCACertStore = messagesCaGenerator.buildCertStore(authorizationCAChain);
    VerifyResult<InnerAtResponse> authResponseResult = messagesCaGenerator.decryptAndVerifyAuthorizationResponseMessage(authResponseMessage,
            authCACertStore, // certificate store containing certificates for auth cert.
            trustStore,
            authTicketSharedKeyReceivers);

==== AuthorizationValidationRequestMessage

To generate and verify AuthorizationValidationRequestMessage

[source, java]

    // The authorization validation request is sent between AA and EA and should
    // contain the SharedATRequest and ecSignature structures.
    AuthorizationValidationRequest authorizationValidationRequest = new AuthorizationValidationRequest(
            innerAtRequest.getSharedAtRequest(),innerAtRequest.getEcSignature());

    EtsiTs103097DataEncryptedUnicast authorizationValidationRequestMessage = messagesCaGenerator.genAuthorizationValidationRequest(
            new Time64(new Date()), // generation Time
            authorizationValidationRequest,
            authorizationCAChain,// The AA certificate chain to generate the signature.
            authorizationCASignKeys.getPrivate(), // The AA signing keys
            enrolmentCACert); // The EA certificate to encrypt data to.

     // To verify an Authorization Validation Request

    RequestVerifyResult<AuthorizationValidationRequest> authorizationValidationRequestVerifyResult = messagesCaGenerator.decryptAndVerifyAuthorizationValidationRequestMessage(
             authorizationValidationRequestMessage,
             authCACertStore, // certificate store containing certificates for auth cert.
             trustStore,
             enrolCAReceipients);

==== AuthorizationValidationResponseMessage

To generate and verify AuthorizationValidationResponseMessage

[source, java]

     // First generate inner authorizationValidationResponse object
    AuthorizationValidationResponse authorizationValidationResponse = new AuthorizationValidationResponse(
            authorizationValidationRequestVerifyResult.getRequestHash(),
            AuthorizationValidationResponseCode.ok,
            genDummyConfirmedSubjectAttributes());
    EtsiTs103097DataEncryptedUnicast authorizationValidationResponseMessage = messagesCaGenerator.genAuthorizationValidationResponseMessage(
            new Time64(new Date()), // generation Time
            authorizationValidationResponse,
            enrollmentCAChain, // EA signing chain
            enrolCASignKeys.getPrivate(), // EA signing private key
            SymmAlgorithm.aes128Ccm, // Encryption algorithm used.
            authorizationValidationRequestVerifyResult.getSecretKey() // The symmetric key generated in the request.
            );

    // To verify an Authorization Validation Response

    Map<HashedId8, Receiver> authValidationSharedKeyReceivers = messagesCaGenerator.buildRecieverStore(new Receiver[] {new PreSharedKeyReceiver(authorizationValidationRequestVerifyResult.getSecretKey())});
    VerifyResult<AuthorizationValidationResponse> authorizationValidationResponseVerifyResult = messagesCaGenerator.decryptAndVerifyAuthorizationValidationResponseMessage(
            authorizationValidationResponseMessage,
            enrolCACertStore,
            trustStore,
            authValidationSharedKeyReceivers);

==== Generate CTL and CRL messages

To generate and verify CTL and CRL messages use:

[source, java]

    // The messages CertificateRevocationListMessage, TlmCertificateTrustListMessage and RcaCertificateTrustListMessage
    // are all generated using very similar methods. Only CertificateRevocationListMessage is shown here.

    // First generate to be signed data
    ToBeSignedCrl toBeSignedCrl = genDummyCRLToBeSignedData();
    EtsiTs103097DataSigned certificateRevocationListMessage = messagesCaGenerator.genCertificateRevocationListMessage(
            new Time64(new Date()), // signing generation time
            toBeSignedCrl,
            new EtsiTs103097Certificate[]{rootCACert}, // certificate chain of signer
            rootCAKeys.getPrivate()); // Private key of signer

    // To verify CTL and CRL messages
    Map<HashedId8, Certificate> crlTrustStore = new HashMap<>(); // Only root ca needed from truststore in this case.
    VerifyResult<ToBeSignedCrl> crlVerifyResult = messagesCaGenerator.verifyCertificateRevocationListMessage(
            certificateRevocationListMessage,
            crlTrustStore,
            trustStore
    );

==== CARequestMessage and Rekey

To generate and verify inital and rekey a CARequestMessage use:

[source, java]

    // First generate inner CaCertificatRequest
    CaCertificateRequest caCertificateRequest = genDummyCaCertificateRequest(authorizationCASignKeys.getPublic());
    // The self sign the message to prove possession.
    EtsiTs103097DataSigned caCertificateRequestMessage = messagesCaGenerator.genCaCertificateRequestMessage(
            new Time64(new Date()), // signing generation time
            caCertificateRequest,
            authorizationCASignKeys.getPublic(), // The CAs signing keys
            authorizationCASignKeys.getPrivate());

   // To verify a CA Request Message

    VerifyResult<CaCertificateRequest> caCertificateRequestVerifyResult = messagesCaGenerator.verifyCACertificateRequestMessage(caCertificateRequestMessage);

    // To generate a Rekey CA Request Message
    CaCertificateRequest caCertificateRekeyRequest = genDummyCaCertificateRequest(authorizationCAReSignKeys.getPublic());
    EtsiTs103097DataSigned caCertificateRekeyRequestMessage =messagesCaGenerator.genCaCertificateRekeyingMessage(
            new Time64(new Date()), // signing generation time,
            caCertificateRekeyRequest,
            authorizationCAChain,
            authorizationCASignKeys.getPrivate(),
            authorizationCAReSignKeys.getPublic(),
            authorizationCAReSignKeys.getPrivate());

    // To Verify a Rekey CA Request Message
    VerifyResult<CaCertificateRequest> caCertificateRekeyRequestVerifyResult = messagesCaGenerator.verifyCACertificateRekeyingMessage(caCertificateRekeyRequestMessage,authCACertStore,trustStore);

== US Standard IEEE 1609.2

The implementation supports the following:

Important: The encryption scheme hasn't been properly tested for inter-operability yet and might contain wrong ECIES parameters.

=== Example Code

Full example code can be seen in src/test/java/org/certificateservices/custom/c2x/demo it contains demo of both ITS (EU) and IEEE (US) standards.

Before doing anything else you need to initialize a CryptoManager used for all cryptographic operations.

[source, java]

    Ieee1609Dot2CryptoManager cryptoManager = new DefaultCryptoManager();   
    // Initialize the crypto manager to use soft keys using the bouncy castle cryptographic provider.
    cryptoManager.setupAndConnect(new DefaultCryptoManagerParams("BC"));

==== Root CA

Example code on how to generate Root a CA, use the AuthorityCertGenerator:

[source, java]

    // Create an authority certificate generator and initialize it with the crypto manager. 
    AuthorityCertGenerator authorityCertGenerator = new AuthorityCertGenerator(cryptoManager);

    // Generate a reference to the Root CA Keys     
    KeyPair rootCASigningKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);
    KeyPair rootCAEncryptionKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);

    CertificateId rootCAId = new CertificateId(new Hostname("Test RootCA"));
    ValidityPeriod rootCAValidityPeriod = new ValidityPeriod(new Date(), DurationChoices.years, 45);
    List<Integer> countries = new ArrayList<Integer>();
    countries.add(SWEDEN);
    GeographicRegion region = GeographicRegion.generateRegionForCountrys(countries);

    // Generate the root CA Certificate, without any encryption keys or geographic region.
    Certificate rootCACertificate = authorityCertGenerator.genRootCA(rootCAId, // CertificateId
            rootCAValidityPeriod, //ValidityPeriod
            region, //GeographicRegion
            4, // assuranceLevel 
            3, // confidenceLevel 
            3, // minChainDepth
            -1, // chainDepthRange
            SignatureChoices.ecdsaNistP256Signature, //signingPublicKeyAlgorithm
            rootCASigningKeys.getPublic(), // signPublicKey
            rootCASigningKeys.getPrivate(), // signPrivateKey
            SymmAlgorithm.aes128Ccm, // symmAlgorithm
            BasePublicEncryptionKeyChoices.ecdsaNistP256,  // encPublicKeyAlgorithm
            rootCAEncryptionKeys.getPublic()); // encPublicKey

==== Enrollment CA (Long Term)

To generate an Enrollment CA:

[source, java]

    // Generate a reference to the Enrollment CA Keys       
    KeyPair enrollmentCASigningKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);
    KeyPair enrollmentCAEncryptionKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);

    CertificateId enrollmentCAId = new CertificateId(new Hostname("Test Enrollment CA"));
    ValidityPeriod enrollmentCAValidityPeriod = new ValidityPeriod(new Date(), DurationChoices.years, 37);

    byte[] cracaid = Hex.decode("010203"); // Some cracaid
    PsidSspRange[] subjectPerms = new PsidSspRange[1];
    subjectPerms[0] = new PsidSspRange(new Psid(5), new SspRange(SspRangeChoices.all, null)); // Insert proper subject permissions here.
    // Generate a reference to the Enrollment CA Signing Keys
    Certificate enrollmentCACertificate =authorityCertGenerator.genLongTermEnrollmentCA(
            CertificateType.explicit, // Implicit or Explicit certificate
            enrollmentCAId,// CertificateId
            enrollmentCAValidityPeriod, 
            region,  //GeographicRegion
            subjectPerms,
            cracaid,
            99, // CrlSeries
            4, // assuranceLevel 
            3, // confidenceLevel 
            2, // minChainDepth
            0, // chainDepthRange
            SignatureChoices.ecdsaNistP256Signature, //signingPublicKeyAlgorithm
            enrollmentCASigningKeys.getPublic(), // signPublicKey, i.e public key in certificate
            rootCACertificate, // signerCertificate
            rootCASigningKeys.getPublic(), // signCertificatePublicKey, must be specified separately to support implicit certificates.
            rootCASigningKeys.getPrivate(),
            SymmAlgorithm.aes128Ccm, // symmAlgorithm
            BasePublicEncryptionKeyChoices.ecdsaNistP256,  // encPublicKeyAlgorithm
            enrollmentCAEncryptionKeys.getPublic() // encryption public key
            );

==== Authorization CA (Short Term)

To generate an Authorization CA:

[source, java]

    // Generate a reference to the Authorization CA Keys
    KeyPair authorityCASigningKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);
    KeyPair authorityCAEncryptionKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);

    CertificateId authorityCAId = new CertificateId(new Hostname("Test Enrollment CA"));
    ValidityPeriod authorityCAValidityPeriod = new ValidityPeriod(new Date(), DurationChoices.years, 15);

    cracaid = Hex.decode("040506"); // Some cracaid
    subjectPerms = new PsidSspRange[1];
    subjectPerms[0] = new PsidSspRange(new Psid(6), new SspRange(SspRangeChoices.all, null)); // Insert proper subject permissions here.

    // Generate a reference to the Authorization CA Signing Keys
    Certificate authorityCACertificate = authorityCertGenerator.genAuthorizationCA(
            CertificateType.explicit, // Implicit or Explicit certificate
            authorityCAId,// CertificateId
            authorityCAValidityPeriod, 
            region,  //GeographicRegion
            subjectPerms,
            cracaid,
            99, // Some CrlSeries
            4, // assuranceLevel 
            3, // confidenceLevel 
            2, // minChainDepth
            0, // chainDepthRange
            SignatureChoices.ecdsaNistP256Signature, //signingPublicKeyAlgorithm
            authorityCASigningKeys.getPublic(), // signPublicKey, i.e public key in certificate
            rootCACertificate, // signerCertificate
            rootCASigningKeys.getPublic(), // signCertificatePublicKey,
            rootCASigningKeys.getPrivate(),
            SymmAlgorithm.aes128Ccm, // symmAlgorithm
            BasePublicEncryptionKeyChoices.ecdsaNistP256,  // encPublicKeyAlgorithm
            authorityCAEncryptionKeys.getPublic() // encryption public key
            );

==== Enrollment Certificate

To create an Enrollment Certificate (explicit in this example) use the EnrollmentCertGenerator.

[source, java]

    // Now we have the CA hierarchy, the next step is to generate an enrollment credential
    // First we create a Enrollment Credential Cert Generator using the newly created Enrollment CA.
    EnrollmentCertGenerator enrollmentCredentialCertGenerator = new EnrollmentCertGenerator(cryptoManager);
    // Next we generate keys for an enrollment credential.
    KeyPair enrollmentCredentialSigningKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);
    // Next we generate keys for an enrollment credential.
    KeyPair enrollmentCredentialEncryptionKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);

    CertificateId enrollCertId = new CertificateId(Hex.decode("0102030405060708"));
    ValidityPeriod enrollCertValidityPeriod = new ValidityPeriod(new Date(), DurationChoices.years, 35);

    PsidSspRange[] certRequestPermissions = new PsidSspRange[1];
    certRequestPermissions[0] = new PsidSspRange(new Psid(5), new SspRange(SspRangeChoices.all, null)); // Insert proper subject permissions here.

    // Then use the following command to generate a enrollment credential
    Certificate enrollmentCredential = enrollmentCredentialCertGenerator.genEnrollCert(
            CertificateType.explicit, // Implicit or Explicit certificate
            enrollCertId, // Certificate Id,
            enrollCertValidityPeriod, 
            region, 
            certRequestPermissions, 
            cracaid, // insert proper cracaid here.
            99, // Some CrlSeries
            4, 
            3, 
            SignatureChoices.ecdsaNistP256Signature, //signingPublicKeyAlgorithm
            enrollmentCredentialSigningKeys.getPublic(), // signPublicKey, i.e public key in certificate
            enrollmentCACertificate, // signerCertificate
            enrollmentCASigningKeys.getPublic(), // signCertificatePublicKey,
            enrollmentCASigningKeys.getPrivate(), 
            SymmAlgorithm.aes128Ccm, // symmAlgorithm 
            BasePublicEncryptionKeyChoices.ecdsaNistP256, // encPublicKeyAlgorithm
            enrollmentCredentialEncryptionKeys.getPublic() // encryption public key
            );

==== Authorization Certificate (With implicit certificate)

To create an Authorization Certificate (implicit in this example) use the AuthorizationCertGenerator.

[source, java]

    // Authorization certificates are created by the AuthorizationCertGenerator
    AuthorizationCertGenerator authorizationCertGenerator = new AuthorizationCertGenerator(cryptoManager);

    // Next we generate keys for an authorization certificate.
    KeyPair authorizationCertRequestSigningKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);

    // Next we generate keys for an authorization certificate.
    KeyPair authorizationCertEncryptionKeys = cryptoManager.generateKeyPair(SignatureChoices.ecdsaNistP256Signature);

    CertificateId authorizationCertId = new CertificateId(Hex.decode("9999999999"));
    ValidityPeriod authorizationCertValidityPeriod = new ValidityPeriod(new Date(), DurationChoices.years, 35);

    PsidSsp[] appPermissions = new PsidSsp[1];
    appPermissions[0] = new PsidSsp(new Psid(6), null); // Insert proper app permissions here.

    // Generate a certificate as an implicit certificate.
    Certificate authorizationCert = authorizationCertGenerator.genAuthorizationCert(
            CertificateType.implicit, // Implicit or Explicit certificate
            authorizationCertId, // Certificate Id,
            authorizationCertValidityPeriod, 
            region, 
            appPermissions, 
            cracaid, // insert proper cracaid here.
            99, // Some CrlSeries
            4, 
            3, 
            SignatureChoices.ecdsaNistP256Signature, //signingPublicKeyAlgorithm
            authorizationCertRequestSigningKeys.getPublic(), // signPublicKey, i.e public key in certificate
            authorityCACertificate, // signerCertificate
            authorityCASigningKeys.getPublic(), // signCertificatePublicKey,
            authorityCASigningKeys.getPrivate(), 
            SymmAlgorithm.aes128Ccm, // symmAlgorithm 
            BasePublicEncryptionKeyChoices.ecdsaNistP256, // encPublicKeyAlgorithm
            authorizationCertEncryptionKeys.getPublic() // encryption public key
            ); 

    // Implicit certificate needs to have it's private key reconstructed. R is given inside the ImplicitCertificateData (which is the actual type of implicit certificates)
    PrivateKey authorizationCertSigningPrivateKey = cryptoManager.reconstructImplicitPrivateKey(authorizationCert, 
            ((ImplicitCertificateData) authorizationCert).getR(), 
            SignatureChoices.ecdsaNistP256Signature, 
            authorizationCertRequestSigningKeys.getPrivate(), authorityCASigningKeys.getPublic(),
            authorityCACertificate);

==== Certificate Encoding and Decoding Example

To encode and decode a certificate use:

[source, java]

    // To encode a certificate to a byte array use the following method
    byte[] certificateData = authorizationCert.getEncoded();

    // To decode certificate data use the following constructor
    Certificate decodedCertificate = new Certificate(certificateData);

==== Secured Data Example

To generate signed and/or encrypted Secured Data use the SecuredMessageGenerator:

[source, java]

    // Secure Messages are created by the Secure Message Generator
    SecuredDataGenerator securedMessageGenerator = new SecuredDataGenerator(SecuredDataGenerator.DEFAULT_VERSION, cryptoManager, HashAlgorithm.sha256, SignatureChoices.ecdsaNistP256Signature);

    // It is then possible to create a signed message with the following code
      // First generate a Header with
    HeaderInfo hi = securedMessageGenerator.genHeaderInfo(
            123L, // psid Required, 
            null, // generationTime Optional
            null, // expiryTime Optional
            null, // generationLocation Optional
            null, // p2pcdLearningRequest Optional
            null, // cracaid Optional
            null, // crlSeries Optional 
            null, // encType Type of encryption when encrypting a message with a encryption key references in a signed message instead of a certificate. Optional
            null, // encryptionKey Optional
            null, // inlineP2pcdRequest Optional
    null // requestedCertificate Optional
            );

    // This method can be used to sign the data
    Ieee1609Dot2Data signedData = securedMessageGenerator.genSignedData(hi, 
            "TestData".getBytes(), // The actual payload message to sign. 
            SignerIdentifierType.HASH_ONLY, // One of  HASH_ONLY, SIGNER_CERTIFICATE, CERT_CHAIN indicating reference data of the signer to include in the message
            new Certificate[] {authorizationCert,authorityCACertificate, rootCACertificate}, // The chain is required even though it isn't included in
              // the message if eventual implicit certificates need to have it's public key reconstructed.
            authorizationCertSigningPrivateKey); // Signing Key

    // The message can be encrypted with the method
      // First construct a list of recipient which have the public key specified either as a symmetric key, certificate or in header of signed data
      // In this example we will use certificate as reciever, see package org.certificateservices.custom.c2x.ieee1609dot2.generator.recipient for more details.
    Ieee1609Dot2Data encryptedData = securedMessageGenerator.encryptData(BasePublicEncryptionKeyChoices.ecdsaNistP256, 
              signedData.getEncoded(), new Recipient[] {new CertificateRecipient(enrollmentCredential)});
      // It is also possible to encrypt using a pre shared key using the encryptDataWithPresharedKey() method.

    // It is also possible to sign and encrypt in one go.
    byte[] encryptedAndSignedMessage = securedMessageGenerator.signAndEncryptData(hi, 
            "TestData2".getBytes(), 
            SignerIdentifierType.HASH_ONLY, 
            new Certificate[] {authorizationCert,authorityCACertificate, rootCACertificate}, 
            authorizationCertSigningPrivateKey, // Important to use the reconstructed private key for implicit certificates
            BasePublicEncryptionKeyChoices.ecdsaNistP256, 
            new Recipient[] {new CertificateRecipient(enrollmentCredential)}).getEncoded();

    // To decrypt and verify a signed message it is possible to use the following
      // First build a truststore of trust anchors (root CA certificate or equivalent)
    Map<HashedId8, Certificate> trustStore = securedMessageGenerator.buildCertStore(new Certificate[] {rootCACertificate});
      // Second build a store of known certificate that might be referenced in the message.
    Map<HashedId8, Certificate> certStore = securedMessageGenerator.buildCertStore(new Certificate[] {authorizationCert, authorityCACertificate});
      // To decrypt build a reciever store of known decryption keys and related receiver info, this can be certificate, signed message containing encryption key
      // in header, symmetric key or pre shared key.
    Map<HashedId8, Receiver> recieverStore = securedMessageGenerator.buildRecieverStore(new Receiver[] { new CertificateReciever(enrollmentCredentialEncryptionKeys.getPrivate(), enrollmentCredential)});
      // Finally perform the decryption with.
    DecryptAndVerifyResult decryptAndVerifyResult = securedMessageGenerator.decryptAndVerifySignedData(encryptedAndSignedMessage,
            certStore, 
            trustStore,
            recieverStore, 
            true, //requiredSignature true if message must be signed otherwise a IllegalArgument is throwm
            true //requireEncryption true if message must be encrypted otherwise a IllegalArgument is throwm
            );
       // The decryptAndVerifyResult contains the inner opaque data, the related header info and signer identifier
       // if related message was signed.

      // It is also possible to use the methods decryptData or verifySignedData (or verifyReferencedSignedData) for alternative methods to verify and decrypt messages.

==== Secured Data Encoding and Decoding Example

To encode and decode a secured data use:

[source, java]

    // To encode a secured message to a byte array use the following method.
    byte[] messageData = signedData.getEncoded();

    // To decode message data use the following constructor.
    Ieee1609Dot2Data decodedMessage = new Ieee1609Dot2Data(messageData);

== Reports

include::ReportSection.adoc[]