public CertificateRequestMessage build()
        throws CRMFException
    {
        ASN1EncodableVector v = new ASN1EncodableVector();

        v.add(new ASN1Integer(certReqId));

        if (!extGenerator.isEmpty())
        {
            templateBuilder.setExtensions(extGenerator.generate());
        }

        v.add(templateBuilder.build());

        if (!controls.isEmpty())
        {
            ASN1EncodableVector controlV = new ASN1EncodableVector();

            for (Iterator it = controls.iterator(); it.hasNext();)
            {
                Control control = (Control)it.next();

                controlV.add(new AttributeTypeAndValue(control.getType(), control.getValue()));
            }

            v.add(new DERSequence(controlV));
        }

        CertRequest request = CertRequest.getInstance(new DERSequence(v));

        v = new ASN1EncodableVector();

        v.add(request);

        if (popSigner != null)
        {
            CertTemplate template = request.getCertTemplate();

            if (template.getSubject() == null || template.getPublicKey() == null)
            {
                SubjectPublicKeyInfo pubKeyInfo = request.getCertTemplate().getPublicKey();
                ProofOfPossessionSigningKeyBuilder builder = new ProofOfPossessionSigningKeyBuilder(pubKeyInfo);

                if (sender != null)
                {
                    builder.setSender(sender);
                }
                else
                {
                    PKMACValueGenerator pkmacGenerator = new PKMACValueGenerator(pkmacBuilder);

                    builder.setPublicKeyMac(pkmacGenerator, password);
                }

                v.add(new ProofOfPossession(builder.build(popSigner)));
            }
            else
            {
                ProofOfPossessionSigningKeyBuilder builder = new ProofOfPossessionSigningKeyBuilder(request);

                v.add(new ProofOfPossession(builder.build(popSigner)));
            }
        }
        else if (popoPrivKey != null)
        {
            v.add(new ProofOfPossession(ProofOfPossession.TYPE_KEY_ENCIPHERMENT, popoPrivKey));
        }
        else if (popRaVerified != null)
        {
            v.add(new ProofOfPossession());
        }

        return new CertificateRequestMessage(CertReqMsg.getInstance(new DERSequence(v)));
    }