1 /*
2  * @(#) $Id: SignCommand.java,v 1.3 2003/07/08 08:13:53 pankaj Exp $
3  *
4  * Copyright (c) 2002-03 by Pankaj Kumar (http://www.pankaj-k.net). 
5  * All rights reserved.
6  *
7  * The license governing the use of this file can be found in the 
8  * root directory of the containing software.
9  */
10package org.jstk.crypt;
11
12import java.util.HashMap;
13import java.security.Signature;
14import java.security.Key;
15import java.security.PrivateKey;
16import java.security.PublicKey;
17
18import org.jstk.*;
19
20public class SignCommand extends JSTKCommandAdapter {
21    private static HashMap defaults = new HashMap();
22    static {
23        defaults.put("algorithm", "SHAwithDSA");
24        defaults.put("keystore", "my.keystore");
25        defaults.put("storepass", "changeit");
26        defaults.put("kstype", "JCEKS");
27        defaults.put("alias", "mykey");
28    }
29
30    public String briefDescription(){
31        String briefDesc = "creates or verifies digital signature";
32        return briefDesc;
33    }
34
35    public String optionsDescription(){
36        String optionsDesc =
37            "  -verify             : verify the signature.\n" +
38            "  -infile <infile>    : message file.\n" +
39            "  -sigfile <sigfile>  : signature file.\n" +
40            "  -sigbytes <sigbytes>: signature bytes in hexadecimal.\n" +
41            "  -algorithm <alg>    : algorithm for signature generation.[" +
42                defaults.get("algorithm") + "]\n" +
43            "  -keyfile <keyfile>  : File having the serialized key.\n" +
44            "  -keystore <keystore>: the keystore.[" +
45            defaults.get("keystore") + "]\n" +
46            "  -storepass <storepass>: Password for keystore.[" +
47            defaults.get("storepass") + "]\n" +
48            "  -kstype <kstype>    : the keystore type.[" +
49            defaults.get("kstype") + "]\n" +
50            "  -alias <alias>      : alias to access the key in the keystore.[" +
51            defaults.get("alias") + "]\n" +
52            "  -keypass <keypass>  : Password for key in the keystore.\n" +
53            "  -provider <provider>: provider name for MessageDigest.\n" +
54            "\n" +
55            "  <<keyinfo>> := (-keyfile <keyfile>|[-keystore <keystore>] [-storepass\n" +
56            "      <storepass>] [-kstype <kstype>] [-alias <alias>] [-keypass <keypass>])\n";
57        return optionsDesc;
58    }
59    public String[] useForms(){
60        String[] useForms = {
61            "-infile <infile> [-sigfile <sigfile>] <<keyinfo>>\n" +
62                "\t[-algorithm <alg>] [-provider <provider>]",
63            "-verify -infile <infile> (-sigfile <sigfile> | -sigbytes\n" +
64                "\t<sigbytes>) <<keyinfo>> [-algorithm <alg>] [-provider <provider>]"
65        };
66        return useForms;
67    }
68    public String[] sampleUses(){
69        String[] sampleUses = {
70            "-infile test.txt -keyfile prv.key",
71            "-verify -infile test.txt -keyfile prv.key -sigbytes <...>",
72            "-infile test.txt -sigfile test.sig",
73            "-verify -infile test.txt -sigfile test.sig"
74        };
75        return sampleUses;
76    }
77
78
79    public Object execute(JSTKArgs args) throws JSTKException{
80        try {
81            args.setDefaults(defaults);
82
83            String providerName = (String)args.get("provider");
84            String algorithm = args.get("algorithm");
85            boolean verify = Boolean.valueOf((String)args.get("verify")).booleanValue();
86            String sigString = args.get("sigbytes");
87            String infile = args.get("infile");
88            String sigfile = args.get("sigfile");
89
90            //Do the validations on arguments
91            if (infile == null)
92                return new JSTKResult(null, false, "no file to be signed");
93
94            Signature sig = null;
95            if (providerName != null)
96                sig = Signature.getInstance(algorithm, providerName);
97            else
98                sig = Signature.getInstance(algorithm);
99
00            byte[] bytes = JSTKUtil.bytesFromFile(infile);
01
02            if (verify){
03                PublicKey key;
04                try {
05                    key = (PublicKey)KeyUtil.getKey(args, PublicKey.class); // Get key from keyfile or keystore
06                } catch (Exception e){
07                    return new JSTKResult(null, false, e.getMessage());
08                }
09                if (sigString != null && sigfile != null)
10                    return new JSTKResult(null, false, "too many signatures to verify against");
11
12                byte[] sigbytesV = null;    // holds the signature bytes supplied for verification.
13                if (sigString != null){
14                    sigbytesV = JSTKUtil.bytesFromHexString(sigString);
15                } else if (sigfile != null){
16                    sigbytesV = JSTKUtil.bytesFromFile(sigfile);
17                } else {
18                    return new JSTKResult(null, false, "no signature to verify against");
19                }
20                sig.initVerify(key);
21                perfData.updateBegin();
22                sig.update(bytes);
23                boolean verified = sig.verify(sigbytesV);
24                perfData.updateEnd(bytes.length);
25
26                if (verified)
27                    return new JSTKResult(Boolean.TRUE, true, "verification succeeded");
28                else
29                    return new JSTKResult(Boolean.FALSE, true, "verification failed");
30            } else {
31                PrivateKey key;
32                try {
33                    key = (PrivateKey)KeyUtil.getKey(args, PrivateKey.class);   // Get key from keyfile or keystore
34                } catch (Exception e){
35                    return new JSTKResult(null, false, e.getMessage());
36                }
37
38                sig.initSign(key);
39                perfData.updateBegin();
40                sig.update(bytes);
41                byte[] sigbytes = sig.sign();
42                perfData.updateEnd(bytes.length);
43                if (sigfile != null){
44                    JSTKUtil.bytesToFile(sigbytes, sigfile);
45                    return new JSTKResult(sigbytes, true, "signature written to file: " + sigfile);
46                } else {
47                    String hexString = JSTKUtil.hexStringFromBytes(sigbytes);
48                    return new JSTKResult(sigbytes, true, "Signature (Hex)::\n" + hexString);
49                }
50            }
51        } catch (Exception exc){
52            throw new JSTKException("DigestCommand execution failed", exc);
53        }
54    }
55
56    public static void main(String[] args) throws Exception {
57        JSTKOptions opts = new JSTKOptions();
58        opts.parse(args, 0);
59        SignCommand signCmd = new SignCommand();
60        JSTKResult result = (JSTKResult)signCmd.execute(opts);
61        System.out.println(result.getText());
62        System.exit(result.isSuccess()? 0 : 1);
63    }
64}