diff --git a/jsign-core/src/main/java/net/jsign/Signable.java b/jsign-core/src/main/java/net/jsign/Signable.java index 0dc76cf3..dc90fea5 100644 --- a/jsign-core/src/main/java/net/jsign/Signable.java +++ b/jsign-core/src/main/java/net/jsign/Signable.java @@ -22,23 +22,14 @@ import java.nio.charset.Charset; import java.security.MessageDigest; import java.util.List; +import java.util.ServiceLoader; import org.bouncycastle.asn1.ASN1Object; import org.bouncycastle.asn1.cms.ContentInfo; import org.bouncycastle.cms.CMSSignedData; -import net.jsign.appx.APPXFile; import net.jsign.asn1.authenticode.AuthenticodeObjectIdentifiers; -import net.jsign.cat.CatalogFile; -import net.jsign.mscab.MSCabinetFile; -import net.jsign.msi.MSIFile; -import net.jsign.navx.NAVXFile; -import net.jsign.pe.PEFile; -import net.jsign.script.JScript; -import net.jsign.script.PowerShellScript; -import net.jsign.script.PowerShellXMLScript; -import net.jsign.script.VBScript; -import net.jsign.script.WindowsScript; +import net.jsign.spi.SignableProvider; /** * A file that can be signed with Authenticode. @@ -138,48 +129,12 @@ static Signable of(File file) throws IOException { * @throws UnsupportedOperationException if the file specified isn't supported */ static Signable of(File file, Charset encoding) throws IOException { - if (PEFile.isPEFile(file)) { - return new PEFile(file); - - } else if (MSIFile.isMSIFile(file)) { - return new MSIFile(file); - - } else if (MSCabinetFile.isMSCabinetFile(file)) { - return new MSCabinetFile(file); - - } else if (CatalogFile.isCatalogFile(file)) { - return new CatalogFile(file); - - } else if (NAVXFile.isNAVXFile(file)) { - return new NAVXFile(file); - - } else if (file.getName().toLowerCase().endsWith(".ps1") - || file.getName().toLowerCase().endsWith(".psd1") - || file.getName().toLowerCase().endsWith(".psm1")) { - return new PowerShellScript(file, encoding); - - } else if (file.getName().toLowerCase().endsWith(".ps1xml")) { - return new PowerShellXMLScript(file, encoding); - - } else if (file.getName().toLowerCase().endsWith(".vbs") - || file.getName().toLowerCase().endsWith(".vbe")) { - return new VBScript(file, encoding); - - } else if (file.getName().toLowerCase().endsWith(".js") - || file.getName().toLowerCase().endsWith(".jse")) { - return new JScript(file, encoding); - - } else if (file.getName().toLowerCase().endsWith(".wsf")) { - return new WindowsScript(file, encoding); - - } else if (file.getName().toLowerCase().endsWith(".msix") - || file.getName().toLowerCase().endsWith(".msixbundle") - || file.getName().toLowerCase().endsWith(".appx") - || file.getName().toLowerCase().endsWith(".appxbundle")) { - return new APPXFile(file); - - } else { - throw new UnsupportedOperationException("Unsupported file: " + file); + for (SignableProvider provider : ServiceLoader.load(SignableProvider.class)) { + if (provider.isSupported(file)) { + return provider.create(file, encoding); + } } + + throw new UnsupportedOperationException("Unsupported file: " + file); } } diff --git a/jsign-core/src/main/java/net/jsign/spi/APPXSignableProvider.java b/jsign-core/src/main/java/net/jsign/spi/APPXSignableProvider.java new file mode 100644 index 00000000..717c86b0 --- /dev/null +++ b/jsign-core/src/main/java/net/jsign/spi/APPXSignableProvider.java @@ -0,0 +1,44 @@ +/** + * Copyright 2024 Emmanuel Bourg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.jsign.spi; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; + +import org.kohsuke.MetaInfServices; + +import net.jsign.Signable; +import net.jsign.appx.APPXFile; + +/** + * {@link SignableProvider} for APPX files. + * + * @since 6.1 + */ +@MetaInfServices(SignableProvider.class) +public class APPXSignableProvider extends ExtensionBasedSignableProvider { + + public APPXSignableProvider() { + super("msix", "msixbundle", "appx", "appxbundle"); + } + + @Override + public Signable create(File file, Charset encoding) throws IOException { + return new APPXFile(file); + } +} diff --git a/jsign-core/src/main/java/net/jsign/spi/CatalogSignableProvider.java b/jsign-core/src/main/java/net/jsign/spi/CatalogSignableProvider.java new file mode 100644 index 00000000..45d93466 --- /dev/null +++ b/jsign-core/src/main/java/net/jsign/spi/CatalogSignableProvider.java @@ -0,0 +1,45 @@ +/** + * Copyright 2024 Emmanuel Bourg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.jsign.spi; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; + +import org.kohsuke.MetaInfServices; + +import net.jsign.Signable; +import net.jsign.cat.CatalogFile; + +/** + * {@link SignableProvider} for Catalog files. + * + * @since 6.1 + */ +@MetaInfServices +public class CatalogSignableProvider implements SignableProvider { + + @Override + public boolean isSupported(File file) { + return CatalogFile.isCatalogFile(file); + } + + @Override + public Signable create(File file, Charset encoding) throws IOException { + return new CatalogFile(file); + } +} diff --git a/jsign-core/src/main/java/net/jsign/spi/ExtensionBasedSignableProvider.java b/jsign-core/src/main/java/net/jsign/spi/ExtensionBasedSignableProvider.java new file mode 100644 index 00000000..5b13f68a --- /dev/null +++ b/jsign-core/src/main/java/net/jsign/spi/ExtensionBasedSignableProvider.java @@ -0,0 +1,42 @@ +/** + * Copyright 2024 Emmanuel Bourg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.jsign.spi; + +import java.io.File; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + * {@link SignableProvider} for files matching a specific extension. + * + * @since 6.1 + */ +public abstract class ExtensionBasedSignableProvider implements SignableProvider { + + private final Set extensions; + + public ExtensionBasedSignableProvider(String... extensions) { + this.extensions = new HashSet<>(Arrays.asList(extensions)); + } + + @Override + public boolean isSupported(File file) { + String extension = file.getName().substring(file.getName().lastIndexOf('.') + 1); + return extensions.contains(extension.toLowerCase()); + } +} diff --git a/jsign-core/src/main/java/net/jsign/spi/JScriptSignableProvider.java b/jsign-core/src/main/java/net/jsign/spi/JScriptSignableProvider.java new file mode 100644 index 00000000..1b3b2688 --- /dev/null +++ b/jsign-core/src/main/java/net/jsign/spi/JScriptSignableProvider.java @@ -0,0 +1,44 @@ +/** + * Copyright 2024 Emmanuel Bourg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.jsign.spi; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; + +import org.kohsuke.MetaInfServices; + +import net.jsign.Signable; +import net.jsign.script.JScript; + +/** + * {@link SignableProvider} for JScript files. + * + * @since 6.1 + */ +@MetaInfServices(SignableProvider.class) +public class JScriptSignableProvider extends ExtensionBasedSignableProvider { + + public JScriptSignableProvider() { + super("js", "jse"); + } + + @Override + public Signable create(File file, Charset encoding) throws IOException { + return new JScript(file, encoding); + } +} diff --git a/jsign-core/src/main/java/net/jsign/spi/MSCabinetSignableProvider.java b/jsign-core/src/main/java/net/jsign/spi/MSCabinetSignableProvider.java new file mode 100644 index 00000000..32a2608f --- /dev/null +++ b/jsign-core/src/main/java/net/jsign/spi/MSCabinetSignableProvider.java @@ -0,0 +1,45 @@ +/** + * Copyright 2024 Emmanuel Bourg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.jsign.spi; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; + +import org.kohsuke.MetaInfServices; + +import net.jsign.Signable; +import net.jsign.mscab.MSCabinetFile; + +/** + * {@link SignableProvider} for Microsoft Cabinet files + * + * @since 6.1 + */ +@MetaInfServices +public class MSCabinetSignableProvider implements SignableProvider { + + @Override + public boolean isSupported(File file) throws IOException { + return MSCabinetFile.isMSCabinetFile(file); + } + + @Override + public Signable create(File file, Charset encoding) throws IOException { + return new MSCabinetFile(file); + } +} diff --git a/jsign-core/src/main/java/net/jsign/spi/MSISignableProvider.java b/jsign-core/src/main/java/net/jsign/spi/MSISignableProvider.java new file mode 100644 index 00000000..e3c799d3 --- /dev/null +++ b/jsign-core/src/main/java/net/jsign/spi/MSISignableProvider.java @@ -0,0 +1,45 @@ +/** + * Copyright 2024 Emmanuel Bourg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.jsign.spi; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; + +import org.kohsuke.MetaInfServices; + +import net.jsign.Signable; +import net.jsign.msi.MSIFile; + +/** + * {@link SignableProvider} for MSI files. + * + * @since 6.1 + */ +@MetaInfServices +public class MSISignableProvider implements SignableProvider { + + @Override + public boolean isSupported(File file) throws IOException { + return MSIFile.isMSIFile(file); + } + + @Override + public Signable create(File file, Charset encoding) throws IOException { + return new MSIFile(file); + } +} diff --git a/jsign-core/src/main/java/net/jsign/spi/NAVXSignableProvider.java b/jsign-core/src/main/java/net/jsign/spi/NAVXSignableProvider.java new file mode 100644 index 00000000..e817bcec --- /dev/null +++ b/jsign-core/src/main/java/net/jsign/spi/NAVXSignableProvider.java @@ -0,0 +1,45 @@ +/** + * Copyright 2024 Emmanuel Bourg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.jsign.spi; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; + +import org.kohsuke.MetaInfServices; + +import net.jsign.Signable; +import net.jsign.navx.NAVXFile; + +/** + * {@link SignableProvider} for NAVX files. + * + * @since 6.1 + */ +@MetaInfServices +public class NAVXSignableProvider implements SignableProvider { + + @Override + public boolean isSupported(File file) throws IOException { + return NAVXFile.isNAVXFile(file); + } + + @Override + public Signable create(File file, Charset encoding) throws IOException { + return new NAVXFile(file); + } +} diff --git a/jsign-core/src/main/java/net/jsign/spi/PESignableProvider.java b/jsign-core/src/main/java/net/jsign/spi/PESignableProvider.java new file mode 100644 index 00000000..402c44a2 --- /dev/null +++ b/jsign-core/src/main/java/net/jsign/spi/PESignableProvider.java @@ -0,0 +1,44 @@ +/** + * Copyright 2024 Emmanuel Bourg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.jsign.spi; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; + +import org.kohsuke.MetaInfServices; + +import net.jsign.Signable; +import net.jsign.pe.PEFile; + +/** + * {@link SignableProvider} for Portable Executable files. + * + * @since 6.1 + */ +@MetaInfServices +public class PESignableProvider implements SignableProvider { + @Override + public boolean isSupported(File file) throws IOException { + return PEFile.isPEFile(file); + } + + @Override + public Signable create(File file, Charset encoding) throws IOException { + return new PEFile(file); + } +} diff --git a/jsign-core/src/main/java/net/jsign/spi/PowerShellSignableProvider.java b/jsign-core/src/main/java/net/jsign/spi/PowerShellSignableProvider.java new file mode 100644 index 00000000..1ee10e48 --- /dev/null +++ b/jsign-core/src/main/java/net/jsign/spi/PowerShellSignableProvider.java @@ -0,0 +1,44 @@ +/** + * Copyright 2024 Emmanuel Bourg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.jsign.spi; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; + +import org.kohsuke.MetaInfServices; + +import net.jsign.Signable; +import net.jsign.script.PowerShellScript; + +/** + * {@link SignableProvider} for PowerShell scripts. + * + * @since 6.1 + */ +@MetaInfServices(SignableProvider.class) +public class PowerShellSignableProvider extends ExtensionBasedSignableProvider { + + public PowerShellSignableProvider() { + super("ps1", "psd1", "psm1"); + } + + @Override + public Signable create(File file, Charset encoding) throws IOException { + return new PowerShellScript(file, encoding); + } +} diff --git a/jsign-core/src/main/java/net/jsign/spi/PowerShellXMLSignableProvider.java b/jsign-core/src/main/java/net/jsign/spi/PowerShellXMLSignableProvider.java new file mode 100644 index 00000000..b95bb120 --- /dev/null +++ b/jsign-core/src/main/java/net/jsign/spi/PowerShellXMLSignableProvider.java @@ -0,0 +1,44 @@ +/** + * Copyright 2024 Emmanuel Bourg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.jsign.spi; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; + +import org.kohsuke.MetaInfServices; + +import net.jsign.Signable; +import net.jsign.script.PowerShellXMLScript; + +/** + * {@link SignableProvider} for PowerShell XML files. + * + * @since 6.1 + */ +@MetaInfServices(SignableProvider.class) +public class PowerShellXMLSignableProvider extends ExtensionBasedSignableProvider { + + public PowerShellXMLSignableProvider() { + super("ps1xml"); + } + + @Override + public Signable create(File file, Charset encoding) throws IOException { + return new PowerShellXMLScript(file, encoding); + } +} diff --git a/jsign-core/src/main/java/net/jsign/spi/SignableProvider.java b/jsign-core/src/main/java/net/jsign/spi/SignableProvider.java new file mode 100644 index 00000000..a7229bcd --- /dev/null +++ b/jsign-core/src/main/java/net/jsign/spi/SignableProvider.java @@ -0,0 +1,50 @@ +/** + * Copyright 2024 Emmanuel Bourg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.jsign.spi; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; + +import net.jsign.Signable; + +/** + * Service Provider Interface for {@link Signable} implementations + * + * @since 6.1 + */ +public interface SignableProvider { + + /** + * Tells if the provider supports the specified file. + * + * @param file the file to be signed + * @return true if the provider supports the file, false otherwise + * @throws IOException if an I/O error occurs + */ + boolean isSupported(File file) throws IOException; + + /** + * Creates a Signable instance for the specified file. + * + * @param file the file to be signed + * @param encoding the character encoding (for text files only). + * @return the signable object for the specified file + * @throws IOException if an I/O error occurs + */ + Signable create(File file, Charset encoding) throws IOException; +} diff --git a/jsign-core/src/main/java/net/jsign/spi/VBScriptSignableProvider.java b/jsign-core/src/main/java/net/jsign/spi/VBScriptSignableProvider.java new file mode 100644 index 00000000..ffadd845 --- /dev/null +++ b/jsign-core/src/main/java/net/jsign/spi/VBScriptSignableProvider.java @@ -0,0 +1,44 @@ +/** + * Copyright 2024 Emmanuel Bourg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.jsign.spi; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; + +import org.kohsuke.MetaInfServices; + +import net.jsign.Signable; +import net.jsign.script.VBScript; + +/** + * {@link SignableProvider} for VBScript files. + * + * @since 6.1 + */ +@MetaInfServices(SignableProvider.class) +public class VBScriptSignableProvider extends ExtensionBasedSignableProvider { + + public VBScriptSignableProvider() { + super("vbs", "vbe"); + } + + @Override + public Signable create(File file, Charset encoding) throws IOException { + return new VBScript(file, encoding); + } +} diff --git a/jsign-core/src/main/java/net/jsign/spi/WindowsScriptSignableProvider.java b/jsign-core/src/main/java/net/jsign/spi/WindowsScriptSignableProvider.java new file mode 100644 index 00000000..9d82f3fb --- /dev/null +++ b/jsign-core/src/main/java/net/jsign/spi/WindowsScriptSignableProvider.java @@ -0,0 +1,44 @@ +/** + * Copyright 2024 Emmanuel Bourg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.jsign.spi; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; + +import org.kohsuke.MetaInfServices; + +import net.jsign.Signable; +import net.jsign.script.WindowsScript; + +/** + * {@link SignableProvider} for Windows Script files. + * + * @since 6.1 + */ +@MetaInfServices(SignableProvider.class) +public class WindowsScriptSignableProvider extends ExtensionBasedSignableProvider { + + public WindowsScriptSignableProvider() { + super("wsf"); + } + + @Override + public Signable create(File file, Charset encoding) throws IOException { + return new WindowsScript(file, encoding); + } +} diff --git a/jsign/pom.xml b/jsign/pom.xml index d6d8bc7a..cfb3e0e5 100644 --- a/jsign/pom.xml +++ b/jsign/pom.xml @@ -80,11 +80,19 @@ true + + + org.kohsuke.metainf-services:metainf-services + + *:* - META-INF/** + META-INF/* + META-INF/maven/** + META-INF/services/*log4j* + META-INF/services/*poi* **/*_de.properties **/MavenShadePluginHelper.* **/commons/codec/language/** @@ -126,6 +134,7 @@ jdk.crypto.cryptoki/sun.security.pkcs11.wrapper + @@ -156,6 +165,7 @@ + diff --git a/pom.xml b/pom.xml index 8afb8fd3..69aeed52 100644 --- a/pom.xml +++ b/pom.xml @@ -58,6 +58,13 @@ + + org.kohsuke.metainf-services + metainf-services + 1.1 + true + + junit junit @@ -192,6 +199,7 @@ *.asn1.*,*.zip.* **/ChannelUtils.java + **/?*SignableProvider.java true true