package cn.report.pdf.sign.base;

import com.itextpdf.kernel.PdfException;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.signatures.BouncyCastleDigest;
import com.itextpdf.signatures.DigestAlgorithms;
import com.itextpdf.signatures.IExternalDigest;
import com.itextpdf.signatures.IExternalSignature;
import com.itextpdf.signatures.PdfSignatureAppearance;
import com.itextpdf.signatures.PdfSigner;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;

//由服务器进行加盖签章
public class ClientServerSigning  {
    public static final String SRC = "D:/test/1.pdf";
    public static final String DEST = "D:/test/hello_server.pdf";
    public static final String CERT = "http://demo.itextsupport.com/SigningApp/itextpdf.cer";

    public class ServerSignature implements IExternalSignature {
    	//网站的URL
    	public static final String SIGN = "http://demo.itextsupport.com/SigningApp/signbytes";

        public String getHashAlgorithm() {
            return DigestAlgorithms.SHA256;
        }

        public String getEncryptionAlgorithm() {
            return "RSA";
        }

        public byte[] sign(byte[] message) throws GeneralSecurityException {
            try {
            	//构造URL
                URL url = new URL(SIGN);
                //用URL来构造一个连接
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setDoOutput(true);
                conn.setRequestMethod("POST");
                //连接
                conn.connect();
                OutputStream os = conn.getOutputStream();
                os.write(message);
                os.flush();
                os.close();
                //打开这个页面的输入流，这个网站的内容以字节流的形式返回。如果是网页就返回html，图片就返回图片的内容。
                InputStream is = conn.getInputStream();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] b = new byte[1];
                int read;
                while ((read = is.read(b)) != -1) {
                    baos.write(b, 0, read);
                }
                is.close();
                return baos.toByteArray();
            } catch (IOException e) {
                throw new PdfException(e);
            }
        }
    }

    public void sign(String src, String dest,
                     Certificate[] chain,
                     PdfSigner.CryptoStandard subfilter,
                     String reason, String location)
            throws GeneralSecurityException, IOException {
        // Creating the reader and the signer
        PdfReader reader = new PdfReader(src);
        PdfSigner signer = new PdfSigner(reader, new FileOutputStream(dest), false);
        // Creating the appearance
        PdfSignatureAppearance appearance = signer.getSignatureAppearance()
                .setReason(reason)
                .setLocation(location)
                .setReuseAppearance(false);
        Rectangle rect = new Rectangle(36, 648, 200, 100);
        appearance
                .setPageRect(rect)
                .setPageNumber(1);
        signer.setFieldName("sig");
        // Creating the signature
        IExternalDigest digest = new BouncyCastleDigest();
        IExternalSignature signature = new ServerSignature();
        signer.signDetached(digest, signature, chain, null, null, null, 0, subfilter);
    }

    public static void main(String[] args) throws GeneralSecurityException, IOException {
        CertificateFactory factory = CertificateFactory.getInstance("X.509");
        URL certUrl = new URL(CERT);
        Certificate[] chain = new Certificate[1];
        chain[0] = factory.generateCertificate(certUrl.openStream());
        ClientServerSigning app = new ClientServerSigning();
        app.sign(SRC, DEST, chain, PdfSigner.CryptoStandard.CMS, "Test", "Ghent");
    }

}