1 /*
2  * @(#) $Id: MacCommand.java,v 1.2 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 javax.crypto.Mac;
14import javax.crypto.SecretKey;
15
16import org.jstk.*;
17
18public class MacCommand extends JSTKCommandAdapter {
19    private static HashMap defaults = new HashMap();
20    static {
21        defaults.put("algorithm", "HmacSHA1");
22        defaults.put("keystore", "my.keystore");
23        defaults.put("storepass", "changeit");
24        defaults.put("kstype", "JCEKS");
25        defaults.put("alias", "mykey");
26    }
27
28    public String briefDescription(){
29        String briefDesc = "creates or verifies message authentication code (mac)";
30        return briefDesc;
31    }
32
33    public String optionsDescription(){
34        String optionsDesc =
35            "  -verify             : verify the mac.\n" +
36            "  -infile <infile>    : message file.\n" +
37            "  -macfile <macfile>  : mac file.\n" +
38            "  -macbytes <macbytes>: mac bytes in hexadecimal.\n" +
39            "  -algorithm <alg>    : algorithm for mac generation.[" +
40                defaults.get("algorithm") + "]\n" +
41            "  -keyfile <keyfile>  : File having the serialized key.\n" +
42            "  -keystore <keystore>: the keystore.[" +
43            defaults.get("keystore") + "]\n" +
44            "  -storepass <storepass>: Password for keystore.[" +
45            defaults.get("storepass") + "]\n" +
46            "  -kstype <kstype>    : the keystore type.[" +
47            defaults.get("kstype") + "]\n" +
48            "  -alias <alias>      : alias to access the key in the keystore.[" +
49            defaults.get("alias") + "]\n" +
50            "  -keypass <keypass>  : Password for key in the keystore.\n" +
51            "  -provider <provider>: provider name for MessageDigest.\n" +
52            "\n" +
53            "  <<keyinfo>> := (-keyfile <keyfile>|[-keystore <keystore>] [-storepass\n" +
54            "      <storepass>] [-kstype <kstype>] [-alias <alias>] [-keypass <keypass>])\n";
55        return optionsDesc;
56    }
57    public String[] useForms(){
58        String[] useForms = {
59            "-infile <infile> [-macfile <macfile>] <<keyinfo>>\n" +
60                "\t[-algorithm <alg>] [-provider <provider>]",
61            "-verify -infile <infile> (-macfile <macfile> | -macbytes\n" +
62                "\t<macbytes>) <<keyinfo>> [-algorithm <alg>] [-provider <provider>]"
63        };
64        return useForms;
65    }
66    public String[] sampleUses(){
67        String[] sampleUses = {
68            "-infile test.txt -keyfile prv.key",
69            "-verify -infile test.txt -keyfile prv.key -macbytes <...>",
70            "-infile test.txt -macfile test.mac",
71            "-verify -infile test.txt -macfile test.mac"
72        };
73        return sampleUses;
74    }
75
76
77    public Object execute(JSTKArgs args) throws JSTKException{
78        try {
79            args.setDefaults(defaults);
80
81            String providerName = (String)args.get("provider");
82            String algorithm = args.get("algorithm");
83            boolean verify = Boolean.valueOf((String)args.get("verify")).booleanValue();
84            String macString = args.get("macbytes");
85            String infile = args.get("infile");
86            String macfile = args.get("macfile");
87
88            //Do the validations on arguments
89            if (infile == null)
90                return new JSTKResult(null, false, "no file to be maced");
91
92            Mac mac = null;
93            if (providerName != null)
94                mac = Mac.getInstance(algorithm, providerName);
95            else
96                mac = Mac.getInstance(algorithm);
97
98            byte[] bytes = JSTKUtil.bytesFromFile(infile);
99            SecretKey key;
00            try {
01                key = (SecretKey)KeyUtil.getKey(args, SecretKey.class); // Get key from keyfile or keystore
02            } catch (Exception e){
03                return new JSTKResult(null, false, e.getMessage());
04            }
05            mac.init(key);
06            mac.update(bytes);
07            byte[] macbytes = mac.doFinal();
08
09            if (verify){
10                if (macString != null && macfile != null)
11                    return new JSTKResult(null, false, "too many macs to verify against");
12
13                byte[] macbytesV = null;    // holds the mac bytes supplied for verification.
14                if (macString != null){
15                    macbytesV = JSTKUtil.bytesFromHexString(macString);
16                } else if (macfile != null){
17                    macbytesV = JSTKUtil.bytesFromFile(macfile);
18                } else {
19                    return new JSTKResult(null, false, "no mac to verify against");
20                }
21
22                if (JSTKUtil.equals(macbytes, macbytesV))
23                    return new JSTKResult(Boolean.TRUE, true, "verification succeeded");
24                else
25                    return new JSTKResult(Boolean.FALSE, true, "verification failed");
26            } else {
27                if (macfile != null){
28                    JSTKUtil.bytesToFile(macbytes, macfile);
29                    return new JSTKResult(macbytes, true, "mac written to file: " + macfile);
30                } else {
31                    String hexString = JSTKUtil.hexStringFromBytes(macbytes);
32                    return new JSTKResult(macbytes, true, "Mac (Hex)::\n" + hexString);
33                }
34            }
35        } catch (Exception exc){
36            throw new JSTKException("DigestCommand execution failed", exc);
37        }
38    }
39
40    public static void main(String[] args) throws Exception {
41        JSTKOptions opts = new JSTKOptions();
42        opts.parse(args, 0);
43        SignCommand macCmd = new SignCommand();
44        JSTKResult result = (JSTKResult)macCmd.execute(opts);
45        System.out.println(result.getText());
46        System.exit(result.isSuccess()? 0 : 1);
47    }
48}