/* * A CCNx command line utility. * * Copyright (C) 2008, 2009 Palo Alto Research Center, Inc. * * This work is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 2 as published by the * Free Software Foundation. * This work is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ package org.ccnx.ccn.utils; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.math.BigInteger; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.cert.CertificateEncodingException; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import org.ccnx.ccn.impl.security.crypto.util.CryptoUtil; import org.ccnx.ccn.impl.support.DataUtils; import org.ccnx.ccn.io.content.ContentDecodingException; import org.ccnx.ccn.protocol.ContentObject; import org.ccnx.ccn.protocol.KeyLocator; /** * Command-line utility program to verify CCNx objects stored in a file. */ public class ccn_verify { public static void usage() { System.out.println("ccn_verify [key_file] ccnb_input_file [input_file [input_file...]] (if no key file, input file must contain KEY type key locator)"); } /** * @param args */ public static void main(String[] args) { if (args.length < 1) { usage(); return; } try { PublicKey pubKey = null; int start = 0; if (args.length > 1) { pubKey = readKeyFile(args[0]); start++; } for (int i=start; i < args.length; ++i) { ContentObject co = readObjectFile(args[i]); if ((null == pubKey) && (KeyLocator.KeyLocatorType.KEY == co.signedInfo().getKeyLocator().type())) { pubKey = co.signedInfo().getKeyLocator().key(); } if (null != pubKey) { if (!co.verify(pubKey)) { System.out.println("BAD: Object: " + co.name() + " in file: " + args[i] + " failed to verify."); debugSig(pubKey, co.signature().signature()); } else { System.out.println("GOOD: Object: " + co.name() + " in file: " + args[i] + " verified."); debugSig(pubKey, co.signature().signature()); } } else { System.out.println("NO KEY PROVIDED TO VERIFY OBJECT: " + co.name()); } } } catch (Exception e) { System.out.println("Exception in ccn_verify: " + e.getClass().getName() + ": " + e.getMessage()); e.printStackTrace(); } } public static void debugSig(PublicKey pubKey, byte [] signature) { if (!(pubKey instanceof RSAPublicKey)) { return; } // take it apart RSAPublicKey rsaKey = (RSAPublicKey) pubKey; BigInteger sigInt = new BigInteger(1, signature); BigInteger sigSigInt = new BigInteger(signature); System.out.println("Signature length " + signature.length + " sign? " + sigSigInt.signum()); BigInteger paddedMessage = sigInt.modPow(rsaKey.getPublicExponent(), rsaKey.getModulus()); System.out.println("\nSignature: " + DataUtils.printHexBytes(signature) + "\n"); System.out.println("Inverted signature: " + DataUtils.printHexBytes(paddedMessage.toByteArray()) + "\n"); if (sigSigInt.signum() < 0) { BigInteger paddedSignedMessage = sigSigInt.modPow(rsaKey.getPublicExponent(), rsaKey.getModulus()); System.out.println("Inverted signed signature: " + DataUtils.printHexBytes(paddedSignedMessage.toByteArray()) + "\n"); } } public static ContentObject readObjectFile(String filePath) throws ContentDecodingException, FileNotFoundException { FileInputStream fis = new FileInputStream(filePath); BufferedInputStream bis = new BufferedInputStream(fis); ContentObject co = new ContentObject(); co.decode(bis); return co; } public static PublicKey readKeyFile(String filePath) throws ContentDecodingException, IOException, FileNotFoundException, CertificateEncodingException, InvalidKeySpecException, NoSuchAlgorithmException { ContentObject keyObject = readObjectFile(filePath); try { return CryptoUtil.getPublicKey(keyObject.content()); } catch (InvalidKeySpecException e) { System.out.println("Exception decoding public key! " + filePath + " " + e.getClass().getName() + ": " + e.getMessage()); FileOutputStream fos = new FileOutputStream("contentDump.der"); fos.write(keyObject.content()); fos.close(); throw e; } } }