diff --git a/source/net/filebot/License.java b/source/net/filebot/License.java index fc2dd9a6..ffd8fc1e 100644 --- a/source/net/filebot/License.java +++ b/source/net/filebot/License.java @@ -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 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")); } } diff --git a/source/net/filebot/util/PGP.java b/source/net/filebot/util/PGP.java new file mode 100644 index 00000000..1d7e860b --- /dev/null +++ b/source/net/filebot/util/PGP.java @@ -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; + } + +}