title: PDF document signing with Google KMS and Entrust certificate
body: <p>I am trying to make a valid signature in a pdf document by using a certificate from CA (Entrust) generated with a private key from Google KMS (private key never goes out from the KMS). 
  The certificate chain is made as: [entrustCert, intermediate, rootCert]</p>
  
  <p>Following the part of the code I am using to make this happen:</p>
  
  <pre class="lang-java prettyprint-override"><code>String DEST = "/tmp/test_file.pdf";
  OutputStream outputFile = new FileOutputStream(DEST);
  
  CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
  X509Certificate[] chain = new X509Certificate[3];
  chain[0] = (X509Certificate) certificateFactory.generateCertificate(entrustCert);
  chain[1] = (X509Certificate) certificateFactory.generateCertificate(intermediateCert);
  chain[2] = (X509Certificate) certificateFactory.generateCertificate(rootCert);
  int estimatedSize = 8192;
  
  PdfReader reader = new PdfReader(contract);
  
  ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
  
  PdfStamper stamper = PdfStamper.createSignature(reader, outputStream, '\0');
  
  PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
  appearance.setReason(“reason”);
  appearance.setLocation("Amsterdam");
  appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
  appearance.setCertificate(chain[0]);
  
  PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
  dic.setReason(appearance.getReason());
  dic.setLocation(appearance.getLocation());
  dic.setContact(appearance.getContact());
  dic.setDate(new PdfDate(appearance.getSignDate()));
  appearance.setCryptoDictionary(dic);
  
  HashMap&lt;PdfName, Integer&gt; exc = new HashMap&lt;&gt;();
  exc.put(PdfName.CONTENTS, (estimatedSize * 2 + 2));
  appearance.preClose(exc);
  
  String hashAlgorithm = DigestAlgorithms.SHA256;
  
  BouncyCastleDigest bcd = new BouncyCastleDigest();
  PdfPKCS7 sgn = new PdfPKCS7(null, chain, hashAlgorithm, null, bcd, false);
  
  InputStream data = appearance.getRangeStream();
  byte[] hash = DigestAlgorithms.digest(data, MessageDigest.getInstance("SHA-256"));
  byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, null, null, MakeSignature.CryptoStandard.CMS);
  
  // Creating signature with Google Cloud KMS
  KeyManagementServiceClient client = KeyManagementServiceClient.create();
  AsymmetricSignRequest request = AsymmetricSignRequest.newBuilder()
          .setName("path/of/the/key/in/kms")
          .setDigest(Digest.newBuilder().setSha256(ByteString.copyFrom(hash))) 
          .build();
  AsymmetricSignResponse r = client.asymmetricSign(request);
  byte[] extSignature = r.getSignature().toByteArray();
  
  // Checking if signature is valid
  verifySignatureRSA("path/of/the/key/in/kms", hash, extSignature);
  
  sgn.setExternalDigest(extSignature, null, "RSA");
  TSAClient tsaClient = new TSAClientBouncyCastle("http://timestamp.entrust.net/...");
  estimatedSize += 4192;
  byte[] encodedSig = sgn.getEncodedPKCS7(sh, tsaClient, null, null, MakeSignature.CryptoStandard.CMS);
  byte[] paddedSig = new byte[estimatedSize];
  System.arraycopy(encodedSig, 0, paddedSig, 0, encodedSig.length);
  PdfDictionary dic2 = new PdfDictionary();
  dic2.put(PdfName.CONTENTS, (new PdfString(paddedSig)).setHexWriting(true));
  appearance.close(dic2);
  
  outputStream.writeTo(outputFile);
  </code></pre>
  
  <p>This is the function from <a href="https://cloud.google.com/kms/docs/create-validate-signatures#kms-howto-sign-java" rel="nofollow noreferrer">Google Cloud - Creating and validating digital signatures</a> for the signature verification:</p>
  
  <pre><code>public static boolean verifySignatureRSA(String keyName, byte[] message, byte[] signature)
      throws IOException, GeneralSecurityException {
  
    try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {
      com.google.cloud.kms.v1.PublicKey pub = client.getPublicKey(keyName);
      String pemKey = pub.getPem();
      pemKey = pemKey.replaceFirst("-----BEGIN PUBLIC KEY-----", "");
      pemKey = pemKey.replaceFirst("-----END PUBLIC KEY-----", "");
      pemKey = pemKey.replaceAll("\\s", "");
      byte[] derKey = BaseEncoding.base64().decode(pemKey);
      X509EncodedKeySpec keySpec = new X509EncodedKeySpec(derKey);
      PublicKey rsaKey = KeyFactory.getInstance("RSA").generatePublic(keySpec);
  
      Signature rsaVerify = Signature.getInstance("SHA256withRSA");
      rsaVerify.initVerify(rsaKey);
      rsaVerify.update(message);
      return rsaVerify.verify(signature);
    }
  }
  </code></pre>
  
  <p>Currently I am running in the following issues:</p>
  
  <ol>
  <li>Every signature is invalid: The document has been altered or corrupted since the signature was applied.</li>
  <li>The signature verification from Google is always false. </li>
  </ol>