I have to place a file in remote SFTP server before that I have to sign the file with the private key and they will verify it with the public key. I am getting "PGP Signature verification failed" error from the response file.
So I tried to verify the sign from JAVA. Still, I am getting false value from the signature verify method.
Any help would be appreciated.
Here's a code that I've put together.
public class SignAndVerify {
static final KeyFingerPrintCalculator FP_CALC = new BcKeyFingerprintCalculator();
private static File publicKeyFile = new File("\\publicSign.asc");
private static File privateKeyFile = new File("\\privateSign.asc");
private static final BouncyCastleProvider provider = new BouncyCastleProvider();
static {
Security.addProvider(provider);
}
public static void signFile(String fileName, PGPSecretKey secretKey, String secretPwd, boolean armor, OutputStream out)
throws PGPException {
BCPGOutputStream bOut = null;
OutputStream lOut = null;
InputStream fIn = null;
try {
OutputStream theOut = armor ? new ArmoredOutputStream(out) : out;
PGPPrivateKey pgpPrivKey = secretKey.extractPrivateKey(
new JcePBESecretKeyDecryptorBuilder().setProvider(provider).build(secretPwd.toCharArray()));
PGPSignatureGenerator sGen = new PGPSignatureGenerator(
new JcaPGPContentSignerBuilder(secretKey.getPublicKey().getAlgorithm(), PGPUtil.SHA1)
.setProvider(provider));
sGen.init(PGPSignature.BINARY_DOCUMENT, pgpPrivKey);
Iterator<String> it = secretKey.getPublicKey().getUserIDs();
if (it.hasNext()) {
PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
spGen.setSignerUserID(false, (String) it.next());
sGen.setHashedSubpackets(spGen.generate());
}
bOut = new BCPGOutputStream(theOut);
sGen.generateOnePassVersion(false).encode(bOut);
PGPLiteralDataGenerator lGen = new PGPLiteralDataGenerator();
lOut = lGen.open(bOut, PGPLiteralData.BINARY, "filename", new Date(), new byte[2048]);
fIn = new BufferedInputStream(new FileInputStream(fileName));
byte[] buf = new byte[2048];
int ch;
while ((ch = fIn.read(buf)) >= 0) {
lOut.write(ch);
sGen.update(buf, 0, ch);
}
lGen.close();
sGen.generate().encode(bOut);
theOut.close();
} catch (Exception e) {
throw new PGPException("Error in sign", e);
} finally {
try {
if (bOut != null) {
bOut.close();
}
if(lOut != null) {
lOut.close();
}
if(fIn != null) {
fIn.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static boolean verifyFile(InputStream lin, PGPPublicKey publicKey) throws PGPException {
try {
InputStream in = PGPUtil.getDecoderStream(lin);
JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(in);
/*PGPCompressedData c1 = (PGPCompressedData) pgpFact.nextObject();
pgpFact = new JcaPGPObjectFactory(c1.getDataStream());*/
PGPOnePassSignatureList p1 = (PGPOnePassSignatureList) pgpFact.nextObject();
PGPOnePassSignature ops = p1.get(0);
PGPLiteralData p2 = (PGPLiteralData) pgpFact.nextObject();
InputStream dIn = p2.getInputStream();
int ch;
ops.init(new JcaPGPContentVerifierBuilderProvider().setProvider(provider), publicKey);
while ((ch = dIn.read()) >= 0) {
ops.update((byte) ch);
}
PGPSignatureList p3 = (PGPSignatureList) pgpFact.nextObject();
return ops.verify(p3.get(0));
} catch (Exception e) {
throw new PGPException("Error in verify", e);
}
}
static PGPSecretKey readSecretKey(InputStream input) throws IOException, PGPException {
PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(input),
new JcaKeyFingerprintCalculator());
//
// we just loop through the collection till we find a key suitable for
// encryption, in the real
// world you would probably want to be a bit smarter about this.
//
Iterator<PGPSecretKeyRing> keyRingIter = pgpSec.getKeyRings();
while (keyRingIter.hasNext()) {
PGPSecretKeyRing keyRing = keyRingIter.next();
Iterator<PGPSecretKey> keyIter = keyRing.getSecretKeys();
while (keyIter.hasNext()) {
PGPSecretKey key = keyIter.next();
if (key.isSigningKey()) {
return key;
}
}
}
throw new IllegalArgumentException("Can't find signing key in key ring..");
}
private static PGPPublicKey readPublicKeyFromCol(InputStream in) throws IOException, PGPException {
PGPPublicKeyRing pkRing = null;
PGPPublicKeyRingCollection pkCol = new PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(in), FP_CALC);
println("key ring size=" + pkCol.size());
Iterator<PGPPublicKeyRing> it = pkCol.getKeyRings();
while (it.hasNext()) {
pkRing = it.next();
Iterator<PGPPublicKey> pkIt = pkRing.getPublicKeys();
while (pkIt.hasNext()) {
PGPPublicKey key = pkIt.next();
println("Encryption key = " + key.isEncryptionKey() + ", Master key = " + key.isMasterKey());
if (key.isEncryptionKey())
return key;
}
}
return null;
}
public static void main(String[] args) throws Exception {
println("Inside Class..");
String fileName = "\\fileToBeSigned.xml";
String secretKey = "Passphrase";
String outFileName = "\\signedFile.xml";
OutputStream out = new BufferedOutputStream(new FileOutputStream(outFileName));
InputStream lin = new BufferedInputStream(new FileInputStream(outFileName));
PGPSecretKey pgpSec = readSecretKey(new BufferedInputStream(new FileInputStream(privateKeyFile)));
signFile(fileName, pgpSec, secretKey, true, out);
PGPPublicKey encKey = readPublicKeyFromCol(new FileInputStream(publicKeyFile));
Boolean lverify = verifyFile(lin, encKey);
println("result is ::" + lverify);
out.close();
lin.close();
}
private static void println(String msg) {
System.out.println(msg);
}
}