1
0
mirror of https://github.com/mitb-archive/filebot synced 2024-11-05 08:55:08 -05:00

* Use BC crypto instead of JCA crypto due to strange bugs (see https://www.filebot.net/forums/viewtopic.php?f=6&t=6006&p=34534#p34534)

* Refactor PGP code into a Utilities class
This commit is contained in:
Reinhard Pointner 2018-07-06 01:23:09 +08:00
parent 8ab2bf5d98
commit a1e979af9e
2 changed files with 60 additions and 46 deletions

View File

@ -1,12 +1,11 @@
package net.filebot;
import static java.nio.charset.StandardCharsets.*;
import static java.util.stream.Collectors.*;
import static net.filebot.Settings.*;
import static net.filebot.util.JsonUtilities.*;
import static net.filebot.util.PGP.*;
import static net.filebot.util.RegularExpressions.*;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.Serializable;
@ -21,17 +20,8 @@ import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import org.bouncycastle.bcpg.ArmoredInputStream;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPSignatureList;
import org.bouncycastle.openpgp.jcajce.JcaPGPObjectFactory;
import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
import org.apache.commons.io.IOUtils;
import net.filebot.util.ByteBufferOutputStream;
import net.filebot.util.SystemProperty;
import net.filebot.web.WebRequest;
@ -71,40 +61,10 @@ public class License implements Serializable {
}
private Map<String, String> getProperties(byte[] bytes) throws Exception {
return NEWLINE.splitAsStream(verifyClearSignMessage(bytes)).map(s -> s.split(": ", 2)).collect(toMap(a -> a[0], a -> a[1]));
}
byte[] pub = IOUtils.toByteArray(getClass().getResource("license.key"));
String msg = verifyClearSignMessage(bytes, pub);
private String verifyClearSignMessage(byte[] bytes) throws Exception {
ArmoredInputStream armoredInput = new ArmoredInputStream(new ByteArrayInputStream(bytes));
// read content
ByteBufferOutputStream content = new ByteBufferOutputStream(256);
int character;
while ((character = armoredInput.read()) >= 0 && armoredInput.isClearText()) {
content.write(character);
}
// read public key
PGPPublicKeyRing publicKeyRing = new PGPPublicKeyRing(License.class.getResourceAsStream("license.key"), new JcaKeyFingerprintCalculator());
PGPPublicKey publicKey = publicKeyRing.getPublicKey();
// read signature
PGPSignatureList signatureList = (PGPSignatureList) new JcaPGPObjectFactory(armoredInput).nextObject();
PGPSignature signature = signatureList.get(0);
signature.init(new JcaPGPContentVerifierBuilderProvider(), publicKey);
// normalize clear sign message
String clearSignMessage = NEWLINE.splitAsStream(UTF_8.decode(content.getByteBuffer())).map(String::trim).collect(joining("\r\n"));
// verify signature
signature.update(clearSignMessage.getBytes(UTF_8));
if (!signature.verify()) {
throw new PGPException("Bad Signature");
}
return clearSignMessage;
return NEWLINE.splitAsStream(msg).map(s -> s.split(": ", 2)).collect(toMap(a -> a[0], a -> a[1]));
}
private void verifyLicense(byte[] bytes) throws Exception {
@ -112,7 +72,7 @@ public class License implements Serializable {
Object json = cache.json(id, i -> new URL("https://license.filebot.net/verify/" + i)).fetch((url, modified) -> WebRequest.post(url, bytes, "application/octet-stream", getRequestParameters())).expire(Cache.ONE_MONTH).get();
if (getInteger(json, "status") != 200) {
throw new PGPException(getString(json, "message"));
throw new IllegalStateException(getString(json, "message"));
}
}

View File

@ -0,0 +1,54 @@
package net.filebot.util;
import static java.nio.charset.StandardCharsets.*;
import static java.util.stream.Collectors.*;
import static net.filebot.util.RegularExpressions.*;
import java.io.ByteArrayInputStream;
import org.bouncycastle.bcpg.ArmoredInputStream;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPSignatureList;
import org.bouncycastle.openpgp.bc.BcPGPObjectFactory;
import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
import org.bouncycastle.openpgp.operator.bc.BcPGPContentVerifierBuilderProvider;
public class PGP {
public static String verifyClearSignMessage(byte[] psm, byte[] pub) throws Exception {
ArmoredInputStream armoredInput = new ArmoredInputStream(new ByteArrayInputStream(psm));
// read content
ByteBufferOutputStream content = new ByteBufferOutputStream(256);
int character;
while ((character = armoredInput.read()) >= 0 && armoredInput.isClearText()) {
content.write(character);
}
// read public key
PGPPublicKeyRing publicKeyRing = new PGPPublicKeyRing(pub, new BcKeyFingerprintCalculator());
PGPPublicKey publicKey = publicKeyRing.getPublicKey();
// read signature
PGPSignatureList signatureList = (PGPSignatureList) new BcPGPObjectFactory(armoredInput).nextObject();
PGPSignature signature = signatureList.get(0);
signature.init(new BcPGPContentVerifierBuilderProvider(), publicKey);
// normalize clear sign message
String clearSignMessage = NEWLINE.splitAsStream(UTF_8.decode(content.getByteBuffer())).map(String::trim).collect(joining("\r\n"));
// verify signature
signature.update(clearSignMessage.getBytes(UTF_8));
if (!signature.verify()) {
throw new PGPException("Bad Signature");
}
return clearSignMessage;
}
}