mirror of
				https://github.com/Frooodle/Stirling-PDF.git
				synced 2025-11-01 01:21:18 +01:00 
			
		
		
		
	Merge remote-tracking branch 'origin/main' into licenses
This commit is contained in:
		
						commit
						97b6f0eeb4
					
				@ -1,21 +1,37 @@
 | 
			
		||||
package stirling.software.SPDF.controller.api.security;
 | 
			
		||||
 | 
			
		||||
import java.io.ByteArrayInputStream;
 | 
			
		||||
import java.io.ByteArrayOutputStream;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.InputStreamReader;
 | 
			
		||||
import java.io.OutputStream;
 | 
			
		||||
import java.security.KeyStore;
 | 
			
		||||
import java.security.KeyStoreException;
 | 
			
		||||
import java.security.NoSuchAlgorithmException;
 | 
			
		||||
import java.security.PrivateKey;
 | 
			
		||||
import java.security.Security;
 | 
			
		||||
import java.security.UnrecoverableKeyException;
 | 
			
		||||
import java.security.cert.Certificate;
 | 
			
		||||
import java.security.cert.CertificateException;
 | 
			
		||||
import java.security.cert.CertificateFactory;
 | 
			
		||||
import java.util.Calendar;
 | 
			
		||||
 | 
			
		||||
import org.apache.pdfbox.examples.signature.CreateSignatureBase;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDDocument;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
 | 
			
		||||
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
 | 
			
		||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
 | 
			
		||||
import org.bouncycastle.openssl.PEMDecryptorProvider;
 | 
			
		||||
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
 | 
			
		||||
import org.bouncycastle.openssl.PEMKeyPair;
 | 
			
		||||
import org.bouncycastle.openssl.PEMParser;
 | 
			
		||||
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
 | 
			
		||||
import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
 | 
			
		||||
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
 | 
			
		||||
import org.bouncycastle.operator.InputDecryptorProvider;
 | 
			
		||||
import org.bouncycastle.operator.OperatorCreationException;
 | 
			
		||||
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
 | 
			
		||||
import org.bouncycastle.pkcs.PKCSException;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
@ -65,6 +81,7 @@ public class CertSignController {
 | 
			
		||||
        MultipartFile privateKeyFile = request.getPrivateKeyFile();
 | 
			
		||||
        MultipartFile certFile = request.getCertFile();
 | 
			
		||||
        MultipartFile p12File = request.getP12File();
 | 
			
		||||
        MultipartFile jksfile = request.getJksFile();
 | 
			
		||||
        String password = request.getPassword();
 | 
			
		||||
        Boolean showSignature = request.isShowSignature();
 | 
			
		||||
        String reason = request.getReason();
 | 
			
		||||
@ -76,23 +93,31 @@ public class CertSignController {
 | 
			
		||||
            throw new IllegalArgumentException("Cert type must be provided");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        InputStream ksInputStream = null;
 | 
			
		||||
        KeyStore ks = null;
 | 
			
		||||
 | 
			
		||||
        switch (certType) {
 | 
			
		||||
            case "PKCS12":
 | 
			
		||||
                ksInputStream = p12File.getInputStream();
 | 
			
		||||
                break;
 | 
			
		||||
            case "PEM":
 | 
			
		||||
                throw new IllegalArgumentException("TODO: PEM not supported yet");
 | 
			
		||||
                // ksInputStream = privateKeyFile.getInputStream();
 | 
			
		||||
                // break;
 | 
			
		||||
                ks = KeyStore.getInstance("JKS");
 | 
			
		||||
                ks.load(null);
 | 
			
		||||
                PrivateKey privateKey = getPrivateKeyFromPEM(privateKeyFile.getBytes(), password);
 | 
			
		||||
                Certificate cert = (Certificate) getCertificateFromPEM(certFile.getBytes());
 | 
			
		||||
                ks.setKeyEntry(
 | 
			
		||||
                        "alias", privateKey, password.toCharArray(), new Certificate[] {cert});
 | 
			
		||||
                break;
 | 
			
		||||
            case "PKCS12":
 | 
			
		||||
                ks = KeyStore.getInstance("PKCS12");
 | 
			
		||||
                ks.load(p12File.getInputStream(), password.toCharArray());
 | 
			
		||||
                break;
 | 
			
		||||
            case "JKS":
 | 
			
		||||
                ks = KeyStore.getInstance("JKS");
 | 
			
		||||
                ks.load(jksfile.getInputStream(), password.toCharArray());
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                throw new IllegalArgumentException("Invalid cert type: " + certType);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // TODO: page number
 | 
			
		||||
 | 
			
		||||
        KeyStore ks = getKeyStore(ksInputStream, password);
 | 
			
		||||
        CreateSignature createSignature = new CreateSignature(ks, password.toCharArray());
 | 
			
		||||
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
 | 
			
		||||
        sign(pdf.getBytes(), baos, createSignature, name, location, reason);
 | 
			
		||||
@ -100,12 +125,6 @@ public class CertSignController {
 | 
			
		||||
                baos, pdf.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_signed.pdf");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static KeyStore getKeyStore(InputStream is, String password) throws Exception {
 | 
			
		||||
        KeyStore ks = KeyStore.getInstance("PKCS12");
 | 
			
		||||
        ks.load(is, password.toCharArray());
 | 
			
		||||
        return ks;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void sign(
 | 
			
		||||
            byte[] input,
 | 
			
		||||
            OutputStream output,
 | 
			
		||||
@ -129,14 +148,35 @@ public class CertSignController {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // private byte[] parsePEM(byte[] content) throws IOException {
 | 
			
		||||
    //     PemReader pemReader =
 | 
			
		||||
    //             new PemReader(new InputStreamReader(new ByteArrayInputStream(content)));
 | 
			
		||||
    //     return pemReader.readPemObject().getContent();
 | 
			
		||||
    // }
 | 
			
		||||
    private PrivateKey getPrivateKeyFromPEM(byte[] pemBytes, String password)
 | 
			
		||||
            throws IOException, OperatorCreationException, PKCSException {
 | 
			
		||||
        try (PEMParser pemParser =
 | 
			
		||||
                new PEMParser(new InputStreamReader(new ByteArrayInputStream(pemBytes)))) {
 | 
			
		||||
            Object pemObject = pemParser.readObject();
 | 
			
		||||
            JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
 | 
			
		||||
            PrivateKeyInfo pkInfo;
 | 
			
		||||
            if (pemObject instanceof PKCS8EncryptedPrivateKeyInfo) {
 | 
			
		||||
                InputDecryptorProvider decProv =
 | 
			
		||||
                        new JceOpenSSLPKCS8DecryptorProviderBuilder().build(password.toCharArray());
 | 
			
		||||
                pkInfo = ((PKCS8EncryptedPrivateKeyInfo) pemObject).decryptPrivateKeyInfo(decProv);
 | 
			
		||||
            } else if (pemObject instanceof PEMEncryptedKeyPair) {
 | 
			
		||||
                PEMDecryptorProvider decProv =
 | 
			
		||||
                        new JcePEMDecryptorProviderBuilder().build(password.toCharArray());
 | 
			
		||||
                pkInfo =
 | 
			
		||||
                        ((PEMEncryptedKeyPair) pemObject)
 | 
			
		||||
                                .decryptKeyPair(decProv)
 | 
			
		||||
                                .getPrivateKeyInfo();
 | 
			
		||||
            } else {
 | 
			
		||||
                pkInfo = ((PEMKeyPair) pemObject).getPrivateKeyInfo();
 | 
			
		||||
            }
 | 
			
		||||
            return converter.getPrivateKey(pkInfo);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // private boolean isPEM(byte[] content) {
 | 
			
		||||
    //     String contentStr = new String(content);
 | 
			
		||||
    //     return contentStr.contains("-----BEGIN") && contentStr.contains("-----END");
 | 
			
		||||
    // }
 | 
			
		||||
    private Certificate getCertificateFromPEM(byte[] pemBytes)
 | 
			
		||||
            throws IOException, CertificateException {
 | 
			
		||||
        try (ByteArrayInputStream bis = new ByteArrayInputStream(pemBytes)) {
 | 
			
		||||
            return CertificateFactory.getInstance("X.509").generateCertificate(bis);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ public class SignPDFWithCertRequest extends PDFFile {
 | 
			
		||||
 | 
			
		||||
    @Schema(
 | 
			
		||||
            description = "The type of the digital certificate",
 | 
			
		||||
            allowableValues = {"PKCS12", "PEM"})
 | 
			
		||||
            allowableValues = {"PEM", "PKCS12", "JKS"})
 | 
			
		||||
    private String certType;
 | 
			
		||||
 | 
			
		||||
    @Schema(
 | 
			
		||||
@ -28,6 +28,9 @@ public class SignPDFWithCertRequest extends PDFFile {
 | 
			
		||||
    @Schema(description = "The PKCS12 keystore file (required for PKCS12 type certificates)")
 | 
			
		||||
    private MultipartFile p12File;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "The JKS keystore file (Java Key Store)")
 | 
			
		||||
    private MultipartFile jksFile;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "The password for the keystore or the private key")
 | 
			
		||||
    private String password;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -546,9 +546,11 @@ scalePages.submit=Submit
 | 
			
		||||
certSign.title=Certificate Signing
 | 
			
		||||
certSign.header=Sign a PDF with your certificate (Work in progress)
 | 
			
		||||
certSign.selectPDF=Select a PDF File for Signing: 
 | 
			
		||||
certSign.jksNote=Note: If your certificate type is not listed below, please convert it to a Java Keystore (.jks) file using the keytool command line tool. Then, choose the .jks file option below.
 | 
			
		||||
certSign.selectKey=Select Your Private Key File (PKCS#8 format, could be .pem or .der): 
 | 
			
		||||
certSign.selectCert=Select Your Certificate File (X.509 format, could be .pem or .der): 
 | 
			
		||||
certSign.selectP12=Select Your PKCS#12 Keystore File (.p12 or .pfx) (Optional, If provided, it should contain your private key and certificate): 
 | 
			
		||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
 | 
			
		||||
certSign.certType=Certificate Type
 | 
			
		||||
certSign.password=Enter Your Keystore or Private Key Password (If Any): 
 | 
			
		||||
certSign.showSig=Show Signature
 | 
			
		||||
 | 
			
		||||
@ -546,9 +546,11 @@ scalePages.submit=Submit
 | 
			
		||||
certSign.title=Certificate Signing
 | 
			
		||||
certSign.header=Sign a PDF with your certificate (Work in progress)
 | 
			
		||||
certSign.selectPDF=Select a PDF File for Signing:
 | 
			
		||||
certSign.jksNote=Note: If your certificate type is not listed below, please convert it to a Java Keystore (.jks) file using the keytool command line tool. Then, choose the .jks file option below.
 | 
			
		||||
certSign.selectKey=Select Your Private Key File (PKCS#8 format, could be .pem or .der):
 | 
			
		||||
certSign.selectCert=Select Your Certificate File (X.509 format, could be .pem or .der):
 | 
			
		||||
certSign.selectP12=Select Your PKCS#12 Keystore File (.p12 or .pfx) (Optional, If provided, it should contain your private key and certificate):
 | 
			
		||||
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
 | 
			
		||||
certSign.certType=Certificate Type
 | 
			
		||||
certSign.password=Enter Your Keystore or Private Key Password (If Any):
 | 
			
		||||
certSign.showSig=Show Signature
 | 
			
		||||
 | 
			
		||||
@ -1,135 +1,113 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html th:lang="${#locale.toString()}"
 | 
			
		||||
	th:lang-direction="#{language.direction}"
 | 
			
		||||
	xmlns:th="http://www.thymeleaf.org">
 | 
			
		||||
 | 
			
		||||
<th:block
 | 
			
		||||
	th:insert="~{fragments/common :: head(title=#{certSign.title}, header=#{certSign.header})}"></th:block>
 | 
			
		||||
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
 | 
			
		||||
<th:block th:insert="~{fragments/common :: head(title=#{certSign.title}, header=#{certSign.header})}"></th:block>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
	<div id="page-container">
 | 
			
		||||
		<div id="content-wrap">
 | 
			
		||||
			<div th:insert="~{fragments/navbar.html :: navbar}"></div>
 | 
			
		||||
			<br> <br>
 | 
			
		||||
			<div class="container">
 | 
			
		||||
				<div class="row justify-content-center">
 | 
			
		||||
					<div class="col-md-6">
 | 
			
		||||
						<h2 th:text="#{certSign.header}"></h2>
 | 
			
		||||
 | 
			
		||||
						<form action="api/v1/security/cert-sign" method="post"
 | 
			
		||||
							enctype="multipart/form-data">
 | 
			
		||||
							<div class="mb-3">
 | 
			
		||||
								<label th:text="#{certSign.selectPDF}"></label>
 | 
			
		||||
								<div
 | 
			
		||||
									th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
 | 
			
		||||
							</div>
 | 
			
		||||
							<div class="mb-3">
 | 
			
		||||
								<label for="certType" th:text="#{certSign.certType}"></label> <select
 | 
			
		||||
									class="form-control" id="certType" name="certType">
 | 
			
		||||
									<!--  <option value="" th:text="#{selectFillter}"></option>  -->
 | 
			
		||||
									<option value="PKCS12">PKCS12</option>
 | 
			
		||||
									<!--  <option value="PEM">PEM</option> -->
 | 
			
		||||
								</select>
 | 
			
		||||
    <div id="page-container">
 | 
			
		||||
        <div id="content-wrap">
 | 
			
		||||
            <div th:insert="~{fragments/navbar.html :: navbar}"></div>
 | 
			
		||||
            <br> <br>
 | 
			
		||||
            <div class="container">
 | 
			
		||||
                <div class="row justify-content-center">
 | 
			
		||||
                    <div class="col-md-6">
 | 
			
		||||
                        <h2 th:text="#{certSign.header}"></h2>
 | 
			
		||||
                        <form action="api/v1/security/cert-sign" method="post" enctype="multipart/form-data">
 | 
			
		||||
                            <div class="mb-3">
 | 
			
		||||
                                <label th:text="#{certSign.selectPDF}"></label>
 | 
			
		||||
                                <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <!-- Tell users to use keytool to generate JKS for other formats -->
 | 
			
		||||
                            <div class="mb-3">
 | 
			
		||||
								<label th:text="#{certSign.jksNote}"></label>
 | 
			
		||||
							</div>
 | 
			
		||||
                            <div class="mb-3">
 | 
			
		||||
                                <label for="certType" th:text="#{certSign.certType}"></label> <select class="form-control" id="certType" name="certType">
 | 
			
		||||
                                    <option value="" th:text="#{selectFillter}"></option>
 | 
			
		||||
                                    <option value="PEM">PEM</option>
 | 
			
		||||
                                    <option value="PKCS12">PKCS12</option>
 | 
			
		||||
                                    <option value="JKS">JKS</option>
 | 
			
		||||
                                </select>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div id="pemGroup" style="display: none;">
 | 
			
		||||
                                <div class="mb-3">
 | 
			
		||||
                                    <label th:text="#{certSign.selectKey}"></label>
 | 
			
		||||
                                    <div th:replace="~{fragments/common :: fileSelector(name='privateKeyFile', multiple=false, notRequired=true, accept='.pem,.der')}"></div>
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="mb-3">
 | 
			
		||||
                                    <label th:text="#{certSign.selectCert}"></label>
 | 
			
		||||
                                    <div th:replace="~{fragments/common :: fileSelector(name='certFile', multiple=false, notRequired=true, accept='.pem,.der')}"></div>
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div class="mb-3" id="p12Group" style="display: none;">
 | 
			
		||||
                                <label th:text="#{certSign.selectP12}"></label>
 | 
			
		||||
                                <div th:replace="~{fragments/common :: fileSelector(name='p12File', notRequired=true, multiple=false, accept='.p12,.pfx')}"></div>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div class="mb-3" id="jksGroup" style="display: none;">
 | 
			
		||||
                                <label th:text="#{certSign.selectJKS}"></label>
 | 
			
		||||
                                <div th:replace="~{fragments/common :: fileSelector(name='jksFile', notRequired=true, multiple=false, accept='.jks,.keystore')}"></div>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div class="mb-3">
 | 
			
		||||
                                <label th:text="#{certSign.password}"></label> <input type="password" class="form-control" id="password" name="password">
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div class="mb-3">
 | 
			
		||||
                                <label><input type="checkbox" id="showSignature" name="showSignature" th:text="#{certSign.showSig}"></label>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div id="signatureDetails" style="display: none;">
 | 
			
		||||
                                <div class="mb-3">
 | 
			
		||||
                                    <label for="reason" th:text="#{certSign.reason}"></label> <input type="text" class="form-control" id="reason" name="reason">
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="mb-3">
 | 
			
		||||
                                    <label for="location" th:text="#{certSign.location}"></label> <input type="text" class="form-control" id="location" name="location">
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="mb-3">
 | 
			
		||||
                                    <label for="name" th:text="#{certSign.name}"></label> <input type="text" class="form-control" id="name" name="name">
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="mb-3">
 | 
			
		||||
                                    <label for="pageNumber" th:text="#{pageNum}"></label> <input type="number" class="form-control" id="pageNumber" name="pageNumber" min="1" disabled>
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div class="mb-3 text-center">
 | 
			
		||||
                                <button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{certSign.submit}"></button>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </form>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div th:insert="~{fragments/footer.html :: footer}"></div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <script type="text/javascript">
 | 
			
		||||
    document
 | 
			
		||||
    	.getElementById('certType')
 | 
			
		||||
        .addEventListener(
 | 
			
		||||
            'change',
 | 
			
		||||
            function() {
 | 
			
		||||
                var pemGroup = document.getElementById('pemGroup');
 | 
			
		||||
                var p12Group = document.getElementById('p12Group');
 | 
			
		||||
                var jksGroup = document.getElementById('jksGroup');
 | 
			
		||||
                var valueToGroupMap = {
 | 
			
		||||
                    'PEM': pemGroup,
 | 
			
		||||
                    'PKCS12': p12Group,
 | 
			
		||||
                    'JKS': jksGroup
 | 
			
		||||
                };
 | 
			
		||||
                for (var key in valueToGroupMap) {
 | 
			
		||||
                    valueToGroupMap[key].style.display = (this.value === key) ? 'block' : 'none';
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
							<div class="mb-3" id="p12Group" style="display: none;">
 | 
			
		||||
								<label th:text="#{certSign.selectP12}"></label>
 | 
			
		||||
								<div
 | 
			
		||||
									th:replace="~{fragments/common :: fileSelector(name='p12File', notRequired=true, multiple=false, accept='.p12,.pfx')}"></div>
 | 
			
		||||
							</div>
 | 
			
		||||
 | 
			
		||||
							<div id="pemGroup" style="display: none;">
 | 
			
		||||
								<div class="mb-3">
 | 
			
		||||
									<label th:text="#{certSign.selectKey}"></label>
 | 
			
		||||
									<div
 | 
			
		||||
										th:replace="~{fragments/common :: fileSelector(name='privateKeyFile', multiple=false, notRequired=true, accept='.pem,.der')}"></div>
 | 
			
		||||
								</div>
 | 
			
		||||
								<div class="mb-3">
 | 
			
		||||
									<label th:text="#{certSign.selectCert}"></label>
 | 
			
		||||
									<div
 | 
			
		||||
										th:replace="~{fragments/common :: fileSelector(name='certFile', multiple=false, notRequired=true, accept='.pem,.der')}"></div>
 | 
			
		||||
								</div>
 | 
			
		||||
							</div>
 | 
			
		||||
 | 
			
		||||
							<div class="mb-3">
 | 
			
		||||
								<label th:text="#{certSign.password}"></label> <input
 | 
			
		||||
									type="password" class="form-control" id="password"
 | 
			
		||||
									name="password">
 | 
			
		||||
							</div>
 | 
			
		||||
                            
 | 
			
		||||
							<div class="mb-3">
 | 
			
		||||
								<label><input type="checkbox" id="showSignature"
 | 
			
		||||
									name="showSignature" th:text="#{certSign.showSig}"></label>
 | 
			
		||||
							</div>
 | 
			
		||||
 | 
			
		||||
							<div id="signatureDetails" style="display: none;">
 | 
			
		||||
								<div class="mb-3">
 | 
			
		||||
									<label for="reason" th:text="#{certSign.reason}"></label> <input type="text"
 | 
			
		||||
										class="form-control" id="reason" name="reason">
 | 
			
		||||
								</div>
 | 
			
		||||
								<div class="mb-3">
 | 
			
		||||
									<label for="location" th:text="#{certSign.location}"></label> <input type="text"
 | 
			
		||||
										class="form-control" id="location" name="location">
 | 
			
		||||
								</div>
 | 
			
		||||
								<div class="mb-3">
 | 
			
		||||
									<label for="name" th:text="#{certSign.name}"></label> <input type="text"
 | 
			
		||||
										class="form-control" id="name" name="name">
 | 
			
		||||
								</div>
 | 
			
		||||
								<div class="mb-3">
 | 
			
		||||
									<label for="pageNumber" th:text="#{pageNum}"></label> <input
 | 
			
		||||
										type="number" class="form-control" id="pageNumber"
 | 
			
		||||
										name="pageNumber" min="1">
 | 
			
		||||
								</div>
 | 
			
		||||
							</div>
 | 
			
		||||
 | 
			
		||||
							<script type="text/javascript">
 | 
			
		||||
								document
 | 
			
		||||
										.getElementById('certType')
 | 
			
		||||
										.addEventListener(
 | 
			
		||||
												'change',
 | 
			
		||||
												function() {
 | 
			
		||||
													var p12Group = document
 | 
			
		||||
															.getElementById('p12Group');
 | 
			
		||||
													var pemGroup = document
 | 
			
		||||
															.getElementById('pemGroup');
 | 
			
		||||
													if (this.value === 'PKCS12') {
 | 
			
		||||
														p12Group.style.display = 'block';
 | 
			
		||||
														pemGroup.style.display = 'none';
 | 
			
		||||
													} else if (this.value === 'PEM') {
 | 
			
		||||
														p12Group.style.display = 'none';
 | 
			
		||||
														pemGroup.style.display = 'block';
 | 
			
		||||
													} else {
 | 
			
		||||
														p12Group.style.display = 'none';
 | 
			
		||||
														pemGroup.style.display = 'none';
 | 
			
		||||
													}
 | 
			
		||||
												});
 | 
			
		||||
 | 
			
		||||
								document
 | 
			
		||||
										.getElementById('showSignature')
 | 
			
		||||
										.addEventListener(
 | 
			
		||||
												'change',
 | 
			
		||||
												function() {
 | 
			
		||||
													var signatureDetails = document
 | 
			
		||||
															.getElementById('signatureDetails');
 | 
			
		||||
													if (this.checked) {
 | 
			
		||||
														signatureDetails.style.display = 'block';
 | 
			
		||||
													} else {
 | 
			
		||||
														signatureDetails.style.display = 'none';
 | 
			
		||||
													}
 | 
			
		||||
												});
 | 
			
		||||
							</script>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							<div class="mb-3 text-center">
 | 
			
		||||
								<button type="submit" id="submitBtn" class="btn btn-primary"
 | 
			
		||||
									th:text="#{certSign.submit}"></button>
 | 
			
		||||
							</div>
 | 
			
		||||
						</form>
 | 
			
		||||
					</div>
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div th:insert="~{fragments/footer.html :: footer}"></div>
 | 
			
		||||
	</div>
 | 
			
		||||
    document
 | 
			
		||||
        .getElementById('showSignature')
 | 
			
		||||
        .addEventListener(
 | 
			
		||||
            'change',
 | 
			
		||||
            function() {
 | 
			
		||||
                var signatureDetails = document.getElementById('signatureDetails');
 | 
			
		||||
                if (this.checked) {
 | 
			
		||||
                    signatureDetails.style.display = 'block';
 | 
			
		||||
                } else {
 | 
			
		||||
                    signatureDetails.style.display = 'none';
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
    </script>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user