Skip to content

Commit

Permalink
Add cert-file option
Browse files Browse the repository at this point in the history
  • Loading branch information
Qwertovsky committed Jan 5, 2024
1 parent 1a0b6d1 commit d65feae
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 12 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ java -jar gost_sign.jar -i file.pdf --pkcs-id test --pkcs-library /usr/lib/librt
```

Options:

option key | argument | default | description
---|---|---|---
-d,--date | text | now | Date of sign (use ISO 8601 format)
--detached | | | Don't include input document to SIG file
-h,--help | | | Print help
-i,--input | file | error | File to sign
--pkcs-id | text | | Certificate id on token. Private and public keys should share this id. Id is ASCII encoded (74657374 = test)
--pkcs-id | text | | Certificate id on token. Private and public keys should share this id. pkcs-tool uses ASCII encoded version (74657374 = test).
--cert-file | text | | Insurer certificate on disk (DER format). The program looks for keys according this certificate
--pkcs-library | file | | Path to PKCS library

Write certificate on token:
Expand All @@ -25,6 +27,12 @@ Write certificate on token:
pkcs11-tool --module /usr/lib/librtpkcs11ecp.so --type cert --login --write-object test.pem --id 74657374
```

Make DER certificate from PEM:

```
openssl x509 -in certificate.pem -out certificate.der -outform DER
```

## Add signature to PDF document
```
java -jar gost_sign.jar -i file.pdf --pkcs-id test --pkcs-library /usr/lib/librtpkcs11ecp.so --pdf --pdf-visual --pdf-position-x 100 --pdf-position-y 100
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/qwertovsky/cert_gost/CliOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public interface CliOptions {
static final String INPUT = "input";
static final String HELP = "help";
static final String PKCS_ID = "pkcs-id";
static final String CERT_FILE = "cert-file";
static final String PKCS_LIBRARY = "pkcs-library";
static final String PFX_FILE = "pfx-file";
static final String PFX_ALIAS = "pfx-alias";
Expand Down
20 changes: 17 additions & 3 deletions src/main/java/com/qwertovsky/cert_gost/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public static void main(String[] args) throws Exception {
StoreType storeType = null;
if (commandLine.hasOption(CliOptions.PFX_FILE)) {
storeType = StoreType.PFX;
} else if (commandLine.hasOption(CliOptions.PKCS_ID)) {
} else if (commandLine.hasOption(CliOptions.PKCS_ID) || commandLine.hasOption(CliOptions.CERT_FILE)) {
storeType = StoreType.PKCS11;
}
if (storeType == null) {
Expand All @@ -106,7 +106,6 @@ public static void main(String[] args) throws Exception {

switch (storeType) {
case PKCS11: {
String certId = commandLine.getOptionValue(CliOptions.PKCS_ID);
String libraryPath = commandLine.getOptionValue(CliOptions.PKCS_LIBRARY);

if (!commandLine.hasOption(CliOptions.PKCS_LIBRARY)) {
Expand All @@ -119,7 +118,14 @@ public static void main(String[] args) throws Exception {
pkcs11 = Native.load(libraryPath, RtPkcs11.class);
pkcsSession = new NativeLong(Pkcs11Constants.CK_INVALID_HANDLE);
Pkcs11Operations.initializePkcs11AndLoginToFirstToken(pkcs11, pkcsSession, String.valueOf(pinChars).getBytes());
store = new PkcsStore(pkcs11, pkcsSession, certId);
String certId = commandLine.getOptionValue(CliOptions.PKCS_ID);
if (certId != null) {
store = new PkcsStore(pkcs11, pkcsSession, certId);
} else {
String certPath = commandLine.getOptionValue(CliOptions.CERT_FILE);
store = new PkcsStore(pkcs11, pkcsSession, new File(certPath));
}

break;
}
case PFX: {
Expand Down Expand Up @@ -232,6 +238,14 @@ private static Options createOptions() {
.build();
cliOptions.addOption(pkcsIdOption);

Option certFileOption = Option.builder()
.longOpt(CliOptions.CERT_FILE)
.argName("cert file on disk")
.desc("Insurer certificate DER file. Private and public keys for this certificate should be on token")
.hasArg(true)
.build();
cliOptions.addOption(certFileOption);

Option pkcsLibraryOption = Option.builder()
.longOpt(CliOptions.PKCS_LIBRARY)
.argName("/usr/lib/library_path.so")
Expand Down
35 changes: 27 additions & 8 deletions src/main/java/com/qwertovsky/cert_gost/store/PkcsStore.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.qwertovsky.cert_gost.store;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -27,17 +29,30 @@ public class PkcsStore implements GostStore {

private final Pkcs11 pkcs11;
private final NativeLong session;
private final String certId;
private final NativeLong privateKey;
private final Pkcs11Signer pkcs11Signer;
private final StreamDigestCalculator digestCalculator;
private final X509CertificateHolder certificateHolder;
private NativeLong privateKey;
private Pkcs11Signer pkcs11Signer;
private StreamDigestCalculator digestCalculator;

public PkcsStore(Pkcs11 pkcs11, NativeLong session, String certId) throws Exception {
this.pkcs11 = pkcs11;
this.session = session;
this.certId = certId;

X509CertificateHolder certificateHolder = getCertificateHolder();

this.certificateHolder = getCertificateHolder(certId);
this.init(pkcs11, session, certificateHolder);
}

public PkcsStore(Pkcs11 pkcs11, NativeLong session, File certFile) throws Exception {
this.pkcs11 = pkcs11;
this.session = session;

try(FileInputStream fis = new FileInputStream(certFile)) {
this.certificateHolder = new X509CertificateHolder(fis.readAllBytes());
}
this.init(pkcs11, session, certificateHolder);
}

private final void init(Pkcs11 pkcs11, NativeLong session, X509CertificateHolder certificateHolder) throws Exception {
privateKey = Pkcs11Operations.findPrivateKeyByCertificateValue(pkcs11, session, certificateHolder.getEncoded());
AlgorithmIdentifier algorithm = certificateHolder.getSignatureAlgorithm();
SignAlgorithm signAlgorithm = SignAlgorithm.byAlgorithm(algorithm);
Expand Down Expand Up @@ -73,14 +88,18 @@ public Digest getDigest(AlgorithmIdentifier digestAlg) throws Exception {

@Override
public X509CertificateHolder getCertificateHolder() throws Exception {
return certificateHolder;
}

private X509CertificateHolder getCertificateHolder(String certId) throws Exception {
System.out.println("Finding signer certificate");
final CK_ATTRIBUTE[] certificateTemplate;
certificateTemplate = (CK_ATTRIBUTE[]) (new CK_ATTRIBUTE()).toArray(3);
certificateTemplate[0].setAttr(Pkcs11Constants.CKA_CLASS, Pkcs11Constants.CKO_CERTIFICATE);
certificateTemplate[1].setAttr(Pkcs11Constants.CKA_ID, certId.getBytes()); // Certificate ID
certificateTemplate[2].setAttr(Pkcs11Constants.CKA_CERTIFICATE_TYPE, Pkcs11Constants.CKC_X_509);

// certificateTemplate[3].setAttr(Pkcs11Constants.CKA_CERTIFICATE_CATEGORY, Constants.CK_CERTIFICATE_CATEGORY_TOKEN_USER);
// certificateTemplate[3].setAttr(Pkcs11Constants.CKA_CERTIFICATE_CATEGORY, Pkcs11Constants.CK_CERTIFICATE_CATEGORY_TOKEN_USER);
byte[] signerCertificateValue = Pkcs11Operations.getFirstCertificateValue(pkcs11, session, certificateTemplate);
X509CertificateHolder certificateHolder = new X509CertificateHolder(signerCertificateValue);
return certificateHolder;
Expand Down

0 comments on commit d65feae

Please sign in to comment.