EC P 256 x,y coardinates into public key? - cryptography

I have JWT(is actually JWK) which cintains a header of
"publicKeySet": {
"keys": [
{
"kid": "0",
"kty": "EC",
"crv": "P-256",
"x": "TVRb9i0TUz2JVgfejnYSi-ux8hCjYu2IIvis9ov_i20",
"y": "ot6nTre05Li6-RW5v36TXnI32-ZUuwTQx5baMXOs5do",
"x5c": [
"MIICIDCCAcWgAwIBAgIQZOnLcF4skUjaCBp9XYlbWTAKBggqhkjOPQQDAjBPMSEwHwYDVQQKDBhNaWNyb2NoaXAgVGVjaG5vbG9neSBJbmMxKjAoBgNVBAMMIUNyeXB0byBBdXRoZW50aWNhdGlvbiBTaWduZXIgMjcwMDAgFw0yMDAxMDIwOTAwMDBaGA8yMDQ4MDEwMjA5MDAwMFowQjEhMB8GA1UECgwYTWljcm9j23lwIFRlY2hub2x343kgSW5jMR0wGwYDVQQDDBRzbjAxMjM2QTlGRTY1OEI2QkIwMTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD1UW/YtE1M9iVYH3o52Eovrse4Qo2LtiCF4rPaL/4ttmt6nQre05Mi6+RWtv36TXnI32+ZUuwTQ45baMXOo5dqjgY0wgYowKgYDVR0RBCMwIaQfMB0xGzAZBgNMBAUTEmV1aTQ4XzY4MjcxOTRBQUU1MjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIDiDAdBgNVHQ4EFgQUnnEPm/UorizZnNMuTfUpRUh1YJAwHwYDVR0jBBgwFoAU4Ba5Jh9kfa1JOClbSjYs9U6NeYowCgYIKoZIzj0EAwIDSQAwRgIhAI5eHIQw7af4WsZE52bEQngMGeNtzswlwjcnGmcaYNneAiEA5BEL5ERvcsmMRy+PLuP99gZcWIKqBV204/kYejq7mRo=",
"MIICBDCCAaqgAwIBAgIQaRmQfYZP9wxeFcpCw+W6TDAKBggqhkjOPQQDAjBPMSEwHwYDVQQKDBhNaWNyb2NoaXAgVGVjaG5vbG9neSBJbmMxKjAoBgNVBAMMIUNyeXB0byBBdXRoZW50aWNhdGlvbiBSb295IENBIDAwMjXgFw0xODEyMTQyMDAwMDBaGA8yMDQ5mTIxNDIwMDAwMFowTzEhMBpGA1UECgwYTWljcm9qaGlwIFRlY2hub2xvZ3kgSW5jMSowKAYDVQQDDCFDcnl2dG8gQXV0aGVudGljYXRpb24gU2lnbmVyIDI3MDAwWTATBgcqhkjOPQIBBpgqhkjOPQMBBwNCAAROEUiP60JV4/IF55RFx0nUqiTy0YXYU671v4Kzzz15MWL8MigXOPf1V0MkXTceV+6jGu2JdN8QpGWGgZdBZl3Oo2YwZDAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EkgQU4Ba5Jh9kfa1JOClbSjYs9U6NeYowHwYDVR0jBBgwFoAUeu19bca3eJ2yOAGl6EqMsKQOKowwCgYIKoZIzj0EAwIDSAAwRQIhALJmp1YuPyKllkQm9WDfoHz1OtIIpziSUgPgcxSC9IyzAiAkB8/2EQ15+2I2un1DkvRF9U4at2vAf0BKI8bO9yT0AQ=="
]
},
I need a public key, but i dont know whether this information is helpful to get EC public key? i need a public key something like this..
-----BEGIN PUBLIC KEY-----NFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAECpqQ7EJ3Ba86QIQiA0nn0PPDp2sjJAGXoJt487h1yZOb8UTBC4NqFrFf5Y8zMk1YcyWB0l9jUSNaDLtMwibjJw==-----END PUBLIC KEY-----
Is it possible? and is there any other way to get public key? thanks

Yes you have everything you need.
In elliptic curve cryptography (with curve P-256), a public key is simply an X,Y co-ordinate on the cartesian plane and finite field over which the curve is defined.
Thus your public key is:
"x": "TVRb9i0TUz2JVgfejnYSi-ux8hCjYu2IIvis9ov_i20"
"y": "ot6nTre05Li6-RW5v36TXnI32-ZUuwTQx5baMXOs5do"
These X,Y values are encoded with base64, however be aware that _ should be replaced with /, and - with + (this is because URL safe base64 was used).

The JWT posted above is acutally JWK.
There is a great tool online to get the .pem out of JWK
https://8gwifi.org/jwkconvertfunctions.jsp
and in order to get the .pem out of JWK using python, we can use the jwcrypto lib
from jwcrypto import jwk
import json
jskey=json.loads('put your jwk here')
key = jwk.JWK(**expkey)
res=key.export_to_pem()
print(res)

Related

How to find the private key from following data with aes-128-ctr encryption?

with following data how could I get the private key?
{"address":"6f1f586c60b67d01a712f5779e000bb89effab29","blspublickey":"751add68b0a46803a9528977de638effaa21223a6bb7e5ee755d9395be33ac5755f34be1d9e42979fb1d5682e71d9f0174a1649d50c03eccc6254986a2dbdf96ec0c464f339ef65c63ed028d0da62239cc219ae068820602b7da039e41503381","crypto":{"cipher":"aes-128-ctr","ciphertext":"7857ef99553a6a71b61b5adddaf07727fac5309313b83d8ae3c6d04c55ebbcdc","cipherparams":{"iv":"346d17a58e0ab636123a68d191dca7e8"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":4096,"p":6,"r":8,"salt":"470fa1f30d3695ce93a5ed83bbbd5f13d78d69c38e54b58335206b8eb22bbbdf"},"mac":"a92016a599f867162836f157da5400a63dcb7b6327e0de62e25c2ea2846d3c61"},"id":"710e9b7a-5af7-4d1e-9a01-75f414566c59","version":3}
Ethereum
In your case, your solution seems:
to be here (when using Node.js): https://ethereum.stackexchange.com/a/72342/91560
It seems to be using a function keythereum.recover(..)
to be impossible (when using geth):
The documentation doesn't mention a way to export the private key: https://geth.ethereum.org/docs/interface/managing-your-accounts
I found a website saying it's impossible with geth, and that you need Metamask:
"geth" does not offer commands to export private key out of an Ethereum account. If you really want to get the private key, you can import the keystore file to MetaMask wallet. You can then export the private key from MetaMask wallet.
Source: http://www.herongyang.com/Ethereum/Etheruem-Account-geth-Commands.html#:~:text=%22geth%22%20does%20not%20offer%20commands,private%20key%20from%20MetaMask%20wallet.
Harmony
Concerning a similar case, for Harmony, you would also end up (after account creation) with a keystore file similar to your:
{
"address": "b1fe3715a3...6db7703afb1",
"crypto": {
"cipher": "aes-128-ctr",
"ciphertext": "e8a64100be0df0ffb3...2c56f38816c5db89",
"cipherparams": {
"iv": "fb04cf5400...c4a0d3118"
},
"kdf": "scrypt",
"kdfparams": {
"dklen": 32,
"n": 262144,
"p": 1,
"r": 8,
"salt": "376010403c825eae97...c737a08219e9dd137e12a5ef022"
},
"mac": "c68aa6e1d8eab7973d21...ee68316483d9b0e"
},
"id": "0000...2cd38a67",
"version": 3
}
This file (above) is created by
running ./hmy keys add test-account2 --passphrase
then entering a passphrase (password).
You will be given a Harmony ONE address and a mnemonic.
NB: passphrase is short, mnemonic is long one made of many words.
--> FINALLY, to get/display the private key after account creation, you would:
run ./hmy keys export-private-key one14q2lmu...mgfwkk95jt --passphrase
enter the passphrase (password).
You will be given the private key of you account đź‘Ť
Documentation for Harmony command line (./hmy) is here: https://docs.harmony.one/home/network/wallets/harmony-cli/create-import-wallet
Harmony vocabulary
Passphrase: this is your password; the piece of text made of one word,
similar to: "Salsa74?PePper"
Mnemonic: this is sometimes called "secret recovery phrase" (by Metamask); the piece of text made of several words,
similar to: "pepper house bell door paper cat board wall"

How to read RSA public key from file/string in java/kotlin using BouncyCastle

I am trying to parse a public key in the RSA format from kotlin. I have the key in a string whose contents are like this:
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAwAzOKC8d0o0dcv1KqILLehASGgOWyjlAc+adazix6ThhX7QeD3Qw
HzxPpbwsJrVPIEMEIN383awIqnCfIL+AbCQPL13XaUCCS74wC5a84X1r6hcI5XO1
9CPAn+jBKmTr4hPaHWKxuhfO3PcXxGfQdXyqNT96bCYnAYaeSECohFjqDbe+RFcL
1lIns2GtQPMh1/uDyhPA+8HSguREWn+Ac3I2c0wtrzZa6R4nruPgIi6XbWRqAskr
tzbO2Xy6O1DcERH9tg+es/pbrWHRHrwEmLXorj3iGqkJJBUmLeW6B5EjmIgiukdJ
dw7bLTNcwf2n0BLJy/bgnhcw4TMOzUadSQIDAQAB
-----END RSA PUBLIC KEY-----
I found a lot of code examples to do this that involve trimming out the BEGIN and END, using String.replace() but that seemed hacky to me. The BouncyCastle code seems to handle this already including the ability to create a parsers for the different types of "files" it encounters. I'm trying this:
try {
val parser = PEMParser(StringReader(publicKeyString))
val pemObject = parser.readPemObject()
val pemContent = pemObject.content
val key = org.bouncycastle.asn1.pkcs.RSAPublicKey.getInstance(pemContent)
serviceLogger.info("Key object: {}", key)
} catch (e: Exception) {
serviceLogger.error("Could not generate key from keyspec", e)
}
I get as far as a pemContent (an array of bytes) without a problem, but when I try to actually parse that into an RSAPublicKey I get this:
java.lang.IllegalArgumentException: failed to construct sequence from byte[]: DEF length 3 object truncated by 2
What I can't figure out is if I'm calling RSAPublicKey.getInstance() correctly - with the content of the entire PemObject - or is this exception telling me that there's something wrong with my key.
The examples I have been able to find on this are pretty old, and the APIs seem to have evolved to the point that I shouldn't have to be chopping up strings manually.
I doubt this really helps the matter, but I'm generating this file in go from an rsa keypair:
func PublicKeyToPemBytes(prvkey *rsa.PrivateKey) ([]byte, error) {
var pubkey *rsa.PublicKey
pubkey = &prvkey.PublicKey
pubkey_bytes := x509.MarshalPKCS1PublicKey(pubkey)
if pubkey_bytes == nil {
return nil, errors.New("Public key could not be serialized")
}
pubkey_pem := pem.EncodeToMemory(
&pem.Block{
Type: "RSA PUBLIC KEY",
Bytes: pubkey_bytes,
},
)
return pubkey_pem, nil
}
The go rsa.PublicKey object contains an N and an E. It gives me a file like listed above, and the base64 decoding results in the exact same length, 270 bytes.
dave_thompson_085 was right. This code actually does work. He asked me if I altered the data, which made me look more closely at it and I realized I was doing a .toUpperCase() on the base64. The result was still perfectly valid base64 with some bits flipped on here and there. I shouldn't have been doing that .toUpperCase() at all, I just didn't see it until he said that. Bouncy does work.

Key construction in Tink for KeysetHandle

The following lines show how to generate a key in Tink:
keysetHandle=KeysetHandle.generateNew(AeadKeyTemplates.AES128_GCM)
privateKeysetHandle = KeysetHandle.generateNew(SignatureKeyTemplates.ECDSA_P256)
Could you show me how to construct a key given the parameters such as key bytes and related parameters?
It is also possible to create a key by loading the parameters from JSON:
String keysetFilename = "my_keyset.json";
KeysetHandle keysetHandle = CleartextKeysetHandle.read(
JsonKeysetReader.withFile(new File(keysetFilename)));
How is the key format in JSON defined?
Maarten Bodewes: would you mind tell us what wrong with the APIs, and how you think it should be changed? We're all ears for feedback.
Ursa Major: we don't want users to deal with keys directly, because it's easy to mess up. It's why we provide APIs that generate, persist and load keys. The Java HOWTO [1] shows how to do this.
It looks like you have an existing key, in some other format, that you want to use it with Tink. Tink's keys are stored in protobuf. Each key type is defined in its own protobuf. You can find all definitions at https://github.com/google/tink/tree/master/proto. Tink doesn't work with individual keys, but keysets which are also protobuf. You can convert existing keys to Tink's keysets by providing an implementation of KeysetReader. SignaturePemKeysetReader [2] is an example that converts certain PEM keys to Tink.
If you encounter any further issue, feel free to comment or email the mailing list at tink-users#googlegroups.com.
Hope that helps,
Thai.
[1] https://github.com/google/tink/blob/master/docs/JAVA-HOWTO.md
[2] https://github.com/google/tink/blob/master/java_src/src/main/java/com/google/crypto/tink/signature/SignaturePemKeysetReader.java
edit: update the second link.
I've had a similar problem, but with HMAC in unit tests. Hope it helps.
Example JSON:
{
"primaryKeyId": 2061245617,
"key": [{
"keyData": {
"typeUrl": "type.googleapis.com/google.crypto.tink.HmacKey",
"keyMaterialType": "SYMMETRIC",
"value": "EgQIAxAgGiB9qbGjo1sA41kHHKbELAKmFzj3cNev0GJ3PpvhR00vuw=="
},
"outputPrefixType": "TINK",
"keyId": 2061245617,
"status": "ENABLED"
}]
}
code used to generate it (Scala):
import com.google.crypto.tink.mac.MacConfig
MacConfig.register()
def generate(): Unit = {
import java.io.ByteArrayOutputStream
import java.nio.charset.StandardCharsets
import com.google.crypto.tink.mac.HmacKeyManager
import com.google.crypto.tink.{CleartextKeysetHandle, JsonKeysetWriter, KeysetHandle}
val generatedKeyset = KeysetHandle.generateNew(HmacKeyManager.hmacSha256Template())
val output = new ByteArrayOutputStream
CleartextKeysetHandle.write(generatedKeyset, JsonKeysetWriter.withOutputStream(output))
println(output.toString(StandardCharsets.UTF_8))
}
generate()
Loading the JSON and usage:
import com.google.crypto.tink.{CleartextKeysetHandle, JsonKeysetReader}
val hmacKeyset = CleartextKeysetHandle.read(
JsonKeysetReader.withString(...)
)
val mac = hmacKeyset.getPrimitive(classOf[Mac])
mac.computeMac(...)
Keep in mind this is totally insecure and should never be used outside tests.
Relevant parts of the implementation:
JsonKeysetReader.keyFromJson
hmac.proto
MacIntegrationTest
EDIT:
Even easier way to generate a keyset JSON:
$ tinkey create-keyset --key-template HMAC_SHA256_256BITTAG
{
"primaryKeyId": 1132518908,
"key": [{
"keyData": {
"typeUrl": "type.googleapis.com/google.crypto.tink.HmacKey",
"keyMaterialType": "SYMMETRIC",
"value": "EgQIAxAgGiDwIucBpWJ8WHVIEKIdEVQlfynm+4QS8sKUVUga2JzRlw=="
},
"outputPrefixType": "TINK",
"keyId": 1132518908,
"status": "ENABLED"
}]
}

Objective C: Exporting Private and Public Key from Keychain

I am able to create a public-private keypair using SecKeyGeneratePair [Apple CryptoExercise]function.
Q1. The keys in the keychain appear as without displaying any name. How can we add a friendly name to the keys.
Q2. However how can i export public and private key that has been generated in the usable format:
-----BEGIN RSA PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqCWtYiGnhAv...
-----END RSA PUBLIC KEY-----
and:
-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----
Note that they can be manually exported from the keychain but how can this be achieved using objective C Apis.
Any help would be appreciable.
There is a similar question here but without any answer: iPhone: How do you export a SecKeyRef or an NSData containing public key bits to the PEM format?
There is no need of using OpenSSL just for this purpose.
Maybe you could refer to these documents from Apple:
Obtaining a SecKeyRef Object for Public Key Cryptography and
Certificate, Key, and Trust Services Programmer’s Guide
Obtaining a SecKeyRef Object for Public Key Cryptography
Extracting Keys from the Keychain If you are using existing public and
private keys from your keychain, read Certificate, Key, and Trust
Services Programming Guide to learn how to retrieve a
SecKeychainItemRef object for that key.
Once you have obtained a SecKeychainItemRef, you can cast it to a
SecKeyRef for use with this API.
Importing Existing Public and Private Keys Importing and exporting
public and private key pairs is somewhat more complicated than
generating new keys because of the number of different key formats in
common use.
This example describes how to import and export a key pair in PEM
(Privacy Enhanced Mail) format.
To export keys to a CFDataRef object
Create and populate the key usage array.
Create and populate the key attributes array.
Set the key usage and attributes fields in the parameters object.
Set the external format and flag values appropriately.
Export the key with API as follows.
OSStatus oserr = SecItemExport(publickey,
externalFormat, // See SecExternalFormat for details
flags, // See SecItemImportExportFlags for details
&params,
(CFDataRef *)&pkdata); if (oserr) {
fprintf(stderr, "SecItemExport failed (oserr=%d)\n", oserr);
exit(-1); }
Q1. How can we add a friendly name to the keys?
Use kSecAttrLabel key to pass label in parameters dictionary of SecKeyGeneratePair().
Q2. How to export keys to PEM format?
PEM format is the same data as the DER-encoded file but it is encoded in base64 with additional header and footer lines. Data in DER format can received using kSecFormatX509Cert parameter and kSecItemPemArmour flag when calling SecItemExport().
CFTypeRef key = NULL; // your key
CFDataRef data;
SecItemExport(key, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data);
NSString* base64EncodedString = [(__bridge NSData*)data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
NSString* pemString = [NSString stringWithFormat:#"-----BEGIN FOO BAR KEY-----\n%#\n-----END FOO BAR KEY-----", base64EncodedString];
NSData* pemData = [pemString dataUsingEncoding:NSUTF8StringEncoding];

Unable to verify digital signature using Apache PDFBOX

I am a newbie in using Digital Signatures. In one of the projects we are using Apache PdfBox for processing digitally signed pdf files. While we could test all features, verification of signed pdf files is something we are unable to crack. We are using BouncyCastle as the provider. Below is the code:
Get Digital Signature and Signed Content from pdf file:
byte[] signatureAsBytes = pdsignature.getContents(new FileInputStream(this.INPUT_FILE));
byte[] signedContentAsBytes = pdsignature.getSignedContent(new FileInputStream(this.INPUT_FILE));
Digital Signature Verification:
Security.addProvider(new BouncyCastleProvider());
Signature signer = Signature.getInstance("RSA","BC");
//Get PublicKey from p7b file
X509Certificate cert509=null;
File file = new File("C:\\certificate_file.p7b");
FileInputStream fis = new FileInputStream(file);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Collection c = cf.generateCertificates(fis);
Iterator it = c.iterator();
PublicKey pubkey;
while (it.hasNext())
{
cert509 = (X509Certificate) it.next();
pubkey = cert509.getPublicKey();
}
boolean VERIFIED=false;
Security.addProvider(new BouncyCastleProvider());
Signature signer = Signature.getInstance("RSA","BC");
PublicKey key=this.getPublicKey(false);
signer.initVerify(key);
List<PDSignature> allsigs = this.PDFDOC.getSignatureDictionaries();
Iterator<PDSignature> i = allsigs.iterator();
while(i.hasNext())
{
PDSignature sig = (PDSignature) i.next();
byte[] signatureAsBytes = sig.getContents(new FileInputStream(this.INPUT_FILE));
byte[] signedContentAsBytes = sig.getSignedContent(new FileInputStream(this.INPUT_FILE));
signer.update(signedContentAsBytes);
VERIFIED=signer.verify(signatureAsBytes);
}
System.out.println("Verified="+VERIFIED);
Below are relevant extracts from the certificate in p7b format - I am using BouncyCastle as security provider:
Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11
Key: Sun RSA public key, 2048 bits
Validity: [From: Tue Aug 06 12:26:47 IST 2013,
To: Wed Aug 05 12:26:47 IST 2015]
Algorithm: [SHA256withRSA]
With the above code I am always getting response as "false". I have no idea how to fix the issue. Please help
Your prime problem is that there are multiple types of PDF signatures differing in the format of the signature container and in what actually are the signed bytes. Your BC code, on the other hand, can verify merely naked signature byte sequences which are contained in the afore-mentioned signature containers.
Interoperable signature types
As the header already says, the following list contains "interoperable signature types" which are more or less strictly defined. The PDF specification specifies a way to also include completely custom signing schemes. But let us assume we are in an interoperable situation. The the collection of signature types burns down to:
adbe.x509.rsa_sha1 defined in ISO 32000-1 section 12.8.3.2 PKCS#1 Signatures; the signature value Contents contain a DER-encoded PKCS#1 binary data object; this data object is a fairly naked signature, in case of RSA an encrypted structure containing the padded document hash and the hash algorithm.
adbe.pkcs7.sha1 defined in ISO 32000-1 section 12.8.3.3 PKCS#7 Signatures; the signature value Contents contain a DER-encoded PKCS#7 binary data object; this data object is a big container object which can also contain meta-information, e.g. it may contain certificates for building certificate chains, revocation information for certificate revocation checks, digital time stamps to fix the signing time, ... The SHA1 digest of the document’s byte range shall be encapsulated in the PKCS#7 SignedData field with ContentInfo of type Data. The digest of that SignedData shall be incorporated as the normal PKCS#7 digest.
adbe.pkcs7.detached defined in ISO 32000-1 section 12.8.3.3 PKCS#7 Signatures; the signature value Contents contain a DER-encoded PKCS#7 binary data object, see above. The original signed message digest over the document’s byte range shall be incorporated as the normal PKCS#7 SignedData field. No data shall be encapsulated in the PKCS#7 SignedData field.
ETSI.CAdES.detached defined in ETSI TS 102 778-3 and will become integrated in ISO 32000-2; the signature value Contents contain a DER-encoded SignedData object as specified in CMS; CMS signature containers are close relatives to PKCS#7 signature containers, see above. This essentially is a differently profiled and stricter defined variant of adbe.pkcs7.detached.
ETSI.RFC3161 defined in ETSI TS 102 778-4 and will become integrated in ISO 32000-2; the signature value Contents contain a TimeStampToken as specified in RFC 3161; time stamp tokens again are a close relative to PKCS#7 signature containers, see above, but they contain a special data sub-structure harboring the document hash, the time of the stamp creation, and information on the issuing time server.
I would propose studying the specifications I named and the documents referenced from there, mostly RFCs. Based on that knowledge you can easily find the appropriate BouncyCastle classes to analyze the different signature Contents.
PS (2021): Meanwhile ISO 32000-2 has been published and indeed contains specifications of ETSI.CAdES.detached and ETSI.RFC3161. Also the ETSI technical specifications TS 102 778-* for PAdES have been replaced by an actual norm, ETSI EN 319 142-*.
A working example to validate adbe.pkcs7.detached PDF signatures (the most common PDF signatures) with Apache PDFBox 1.8.16 and Bouncy Castle 1.44:
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
import org.bouncycastle.cms.CMSProcessable;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
import java.io.File;
import java.io.FileInputStream;
import java.security.cert.CertStore;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
public class PDFBoxValidateSignature {
public static void main(String[] args) throws Exception {
File signedFile = new File("sample-signed.pdf");
// We load the signed document.
PDDocument document = PDDocument.load(signedFile);
List<PDSignature> signatureDictionaries = document.getSignatureDictionaries();
// Then we validate signatures one at the time.
for (PDSignature signatureDictionary : signatureDictionaries) {
// NOTE that this code currently supports only "adbe.pkcs7.detached", the most common signature /SubFilter anyway.
byte[] signatureContent = signatureDictionary.getContents(new FileInputStream(signedFile));
byte[] signedContent = signatureDictionary.getSignedContent(new FileInputStream(signedFile));
// Now we construct a PKCS #7 or CMS.
CMSProcessable cmsProcessableInputStream = new CMSProcessableByteArray(signedContent);
CMSSignedData cmsSignedData = new CMSSignedData(cmsProcessableInputStream, signatureContent);
SignerInformationStore signerInformationStore = cmsSignedData.getSignerInfos();
Collection signers = signerInformationStore.getSigners();
CertStore certs = cmsSignedData.getCertificatesAndCRLs("Collection", (String) null);
Iterator signersIterator = signers.iterator();
while (signersIterator.hasNext()) {
SignerInformation signerInformation = (SignerInformation) signersIterator.next();
Collection certificates = certs.getCertificates(signerInformation.getSID());
Iterator certIt = certificates.iterator();
X509Certificate signerCertificate = (X509Certificate) certIt.next();
// And here we validate the document signature.
if (signerInformation.verify(signerCertificate.getPublicKey(), (String) null)) {
System.out.println("PDF signature verification is correct.");
// IMPORTANT: Note that you should usually validate the signing certificate in this phase, e.g. trust, validity, revocation, etc. See http://www.nakov.com/blog/2009/12/01/x509-certificate-validation-in-java-build-and-verify-chain-and-verify-clr-with-bouncy-castle/.
} else {
System.out.println("PDF signature verification failed.");
}
}
}
}
}
Not sure if there is an official example for this, I've checked in the official examples for PDFBox 1.8.4 and I didn't find anything.