You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ant.apache.org by ma...@apache.org on 2010/08/31 09:47:07 UTC
svn commit: r991108 - in /ant/ivy/core/trunk: ./ doc/ doc/settings/
src/java/org/apache/ivy/core/settings/
src/java/org/apache/ivy/plugins/resolver/
src/java/org/apache/ivy/plugins/signer/
src/java/org/apache/ivy/plugins/signer/bouncycastle/
Author: maartenc
Date: Tue Aug 31 07:47:06 2010
New Revision: 991108
URL: http://svn.apache.org/viewvc?rev=991108&view=rev
Log:
NEW: Ivy can now generate OpenPGP compatible ASCII armored detached signatures when publishing artifacts.
Added:
ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/signer/
ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/signer/SignatureGenerator.java
ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/signer/bouncycastle/
ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/signer/bouncycastle/OpenPGPSignatureGenerator.java
Modified:
ant/ivy/core/trunk/CHANGES.txt
ant/ivy/core/trunk/README
ant/ivy/core/trunk/build-release.xml
ant/ivy/core/trunk/doc/settings/resolvers.html
ant/ivy/core/trunk/doc/toc.json
ant/ivy/core/trunk/ivy.xml
ant/ivy/core/trunk/ivysettings-release.xml
ant/ivy/core/trunk/optional.patterns
ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/IvySettings.java
ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/XmlSettingsParser.java
ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/typedef.properties
ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/resolver/RepositoryResolver.java
ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/resolver/ResolverSettings.java
Modified: ant/ivy/core/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/CHANGES.txt?rev=991108&r1=991107&r2=991108&view=diff
==============================================================================
--- ant/ivy/core/trunk/CHANGES.txt (original)
+++ ant/ivy/core/trunk/CHANGES.txt Tue Aug 31 07:47:06 2010
@@ -115,6 +115,7 @@ for detailed view of each issue, please
- DOCUMENTATION: Grammar, spelling, and clarity of Settings File documentation (IVY-1216) (thanks to Steve Miller)
- DOCUMENTATION: Grammar, spelling, and clarity of Tutorial documentation (IVY-1222) (thanks to Steve Miller)
+- NEW: Ivy can now generate OpenPGP compatible ASCII armored detached signatures when publishing artifacts.
- IMPROVEMENT: the <artifact> child of ivy:publish now accepts any attribute
- IMPROVEMENT: Handle attributes in description subelements (IVY-1214) (thanks to Jean-Louis Boudart)
Modified: ant/ivy/core/trunk/README
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/README?rev=991108&r1=991107&r2=991108&view=diff
==============================================================================
--- ant/ivy/core/trunk/README (original)
+++ ant/ivy/core/trunk/README Tue Aug 31 07:47:06 2010
@@ -53,9 +53,11 @@ code and source code.
The following provides more details on the included cryptographic
software:
-For the Ivy ssh resolver requires the JSch
-<http://www.jcraft.com/jsch/index.html> library.
+The Ivy ssh resolver requires the JSch library
+<http://www.jcraft.com/jsch/index.html>.
The sftp and https resolvers requires the Java Cryptography extensions
<http://java.sun.com/javase/technologies/security/>.
+The PGP signature generator requires the BouncyCastle Java cryptography APIs
+<http://www.bouncycastle.org/java.html>.
Modified: ant/ivy/core/trunk/build-release.xml
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/build-release.xml?rev=991108&r1=991107&r2=991108&view=diff
==============================================================================
--- ant/ivy/core/trunk/build-release.xml (original)
+++ ant/ivy/core/trunk/build-release.xml Tue Aug 31 07:47:06 2010
@@ -18,6 +18,7 @@
-->
<project name="IvyRelease" default="snapshot"
xmlns:ivy="antlib:org.apache.ivy.ant"
+ xmlns:ivy2="antlib:org.apache.ivy.ant_2"
xmlns:xooki="antlib:xooki"
xmlns:openpgp="antlib:org.apache.commons.openpgp.ant">
<import file="build.xml"/>
@@ -471,10 +472,20 @@
</fail>
</target>
- <target name="upload-nexus" depends="release-version, init-ivy">
- <ivy:settings id="upload.settingsId" file="ivysettings-release.xml" />
- <ivy:resolve file="${basedir}/build/artifact/ivy.xml" transitive="false" />
- <ivy:publish organisation="org.apache.ivy"
+ <target name="upload-nexus" depends="release-version, init-ivy, jar">
+ <ivy:retrieve conf="default" pattern="${build.dir}/lib/[artifact]-[revision].[ext]" />
+
+ <taskdef resource="org/apache/ivy/ant/antlib.xml"
+ uri="antlib:org.apache.ivy.ant_2">
+ <classpath>
+ <fileset dir="${artifacts.build.dir}/jars" includes="${final.name}" />
+ <fileset dir="${build.dir}/lib" excludes="ant-*.jar" />
+ </classpath>
+ </taskdef>
+
+ <ivy2:settings id="upload.settingsId" file="ivysettings-release.xml" />
+ <ivy2:resolve file="${basedir}/build/artifact/ivy.xml" transitive="false" />
+ <ivy2:publish organisation="org.apache.ivy"
module="ivy"
revision="${build.version}"
srcivypattern="${basedir}/build/artifact/ivy.xml"
@@ -487,25 +498,7 @@
<artifact name="ivy" ext="pom" type="ivy" />
<artifact name="ivy" ext="jar" type="sources" classifier="sources" />
<artifact name="ivy" ext="jar" type="javadoc" classifier="javadoc" />
-
- <!-- The PGP signatures -->
- <artifact name="ivy" ext="pom.asc" type="asc" />
- <artifact name="ivy" ext="jar.asc" type="asc" />
- <artifact name="ivy" ext="jar.asc" type="asc" classifier="sources" />
- <artifact name="ivy" ext="jar.asc" type="asc" classifier="javadoc" />
-
- <!-- The SHA1 checksums -->
- <artifact name="ivy" ext="pom.sha1" type="sha1" />
- <artifact name="ivy" ext="jar.sha1" type="sha1" />
- <artifact name="ivy" ext="jar.sha1" type="sha1" classifier="sources" />
- <artifact name="ivy" ext="jar.sha1" type="sha1" classifier="javadoc" />
-
- <!-- The MD5 checksums -->
- <artifact name="ivy" ext="pom.md5" type="md5" />
- <artifact name="ivy" ext="jar.md5" type="md5" />
- <artifact name="ivy" ext="jar.md5" type="md5" classifier="sources" />
- <artifact name="ivy" ext="jar.md5" type="md5" classifier="javadoc" />
- </ivy:publish>
+ </ivy2:publish>
</target>
<target name="prepare-snapshot"
Modified: ant/ivy/core/trunk/doc/settings/resolvers.html
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/doc/settings/resolvers.html?rev=991108&r1=991107&r2=991108&view=diff
==============================================================================
--- ant/ivy/core/trunk/doc/settings/resolvers.html (original)
+++ ant/ivy/core/trunk/doc/settings/resolvers.html Tue Aug 31 07:47:06 2010
@@ -169,6 +169,11 @@ By using such a resolver at the beginnin
<td>No</td>
<td>Yes</td>
</tr>
+ <tr><td>signer</td><td>The name of the [[settings/signers detached signature generator]] to use when publishing artifacts. <span class="since">(since 2.2)</span></td>
+ <td>No, by default published artifacts will not get signed by Ivy.</td>
+ <td>No</td>
+ <td>Yes</td>
+ </tr>
</tbody>
</table>
Modified: ant/ivy/core/trunk/doc/toc.json
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/doc/toc.json?rev=991108&r1=991107&r2=991108&view=diff
==============================================================================
--- ant/ivy/core/trunk/doc/toc.json (original)
+++ ant/ivy/core/trunk/doc/toc.json Tue Aug 31 07:47:06 2010
@@ -193,6 +193,13 @@
]
},
{
+ "id":"settings/signers",
+ "title":"signers",
+ "children": [
+
+ ]
+ },
+ {
"id":"settings/lock-strategies",
"title":"lock-strategies",
"children": [
Modified: ant/ivy/core/trunk/ivy.xml
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/ivy.xml?rev=991108&r1=991107&r2=991108&view=diff
==============================================================================
--- ant/ivy/core/trunk/ivy.xml (original)
+++ ant/ivy/core/trunk/ivy.xml Tue Aug 31 07:47:06 2010
@@ -50,6 +50,7 @@
<dependency org="oro" name="oro" rev="2.0.8" conf="default,oro->default"/>
<dependency org="commons-vfs" name="commons-vfs" rev="1.0" conf="default,vfs->default" />
<dependency org="com.jcraft" name="jsch" rev="0.1.31" conf="default,sftp->default" />
+ <dependency org="org.bouncycastle" name="bcpg-jdk14" rev="1.45" conf="default" />
<!-- Test dependencies -->
<dependency org="junit" name="junit" rev="3.8.2" conf="test->default" />
Modified: ant/ivy/core/trunk/ivysettings-release.xml
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/ivysettings-release.xml?rev=991108&r1=991107&r2=991108&view=diff
==============================================================================
--- ant/ivy/core/trunk/ivysettings-release.xml (original)
+++ ant/ivy/core/trunk/ivysettings-release.xml Tue Aug 31 07:47:06 2010
@@ -17,8 +17,13 @@
under the License.
-->
<ivysettings>
- <property name="upload.url" value="https://repository.apache.org/service/local/staging/deploy/maven2"/>
+ <property name="upload.url" value="https://repository.apache.org/service/local/staging/deploy/maven2" />
+ <property name="pgp.keyId" value="auto" override="false" />
<credentials host="repository.apache.org" realm="Sonatype Nexus Repository Manager" username="${upload.user}" passwd="${upload.password}"/>
+
+ <signers>
+ <pgp name="apache-sig" secring="${user.home}/.gnupg/secring.gpg" password="${pgp.password}" keyId="${pgp.keyId}"/>
+ </signers>
<settings defaultResolver="default" />
<resolvers>
@@ -26,7 +31,7 @@
<ibiblio name="public" m2compatible="true" />
<ibiblio name="snapshot" m2compatible="true" root="http://people.apache.org/repo/m2-snapshot-repository" />
</chain>
- <url name="nexus" m2compatible="true" checksums="">
+ <url name="nexus" m2compatible="true" signer="apache-sig">
<artifact pattern="${upload.url}/[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]" />
</url>
</resolvers>
Modified: ant/ivy/core/trunk/optional.patterns
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/optional.patterns?rev=991108&r1=991107&r2=991108&view=diff
==============================================================================
--- ant/ivy/core/trunk/optional.patterns (original)
+++ ant/ivy/core/trunk/optional.patterns Tue Aug 31 07:47:06 2010
@@ -30,6 +30,7 @@ org/apache/ivy/plugins/resolver/SshResol
org/apache/ivy/plugins/resolver/VfsResolver.java
org/apache/ivy/plugins/resolver/VsftpResolver.java
org/apache/ivy/plugins/resolver/packager/*.java
+org/apache/ivy/plugins/signer/bouncycastle/**/*.java
org/apache/ivy/util/url/HttpClientHandler.java
#This section defines the resources to copy for ivy-optional.jar
Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/IvySettings.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/IvySettings.java?rev=991108&r1=991107&r2=991108&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/IvySettings.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/IvySettings.java Tue Aug 31 07:47:06 2010
@@ -92,6 +92,7 @@ import org.apache.ivy.plugins.resolver.C
import org.apache.ivy.plugins.resolver.DependencyResolver;
import org.apache.ivy.plugins.resolver.DualResolver;
import org.apache.ivy.plugins.resolver.ResolverSettings;
+import org.apache.ivy.plugins.signer.SignatureGenerator;
import org.apache.ivy.plugins.trigger.Trigger;
import org.apache.ivy.plugins.version.ChainVersionMatcher;
import org.apache.ivy.plugins.version.ExactVersionMatcher;
@@ -155,6 +156,9 @@ public class IvySettings implements Sort
// Map (String name -> RepositoryCacheManager)
private Map repositoryCacheManagers = new HashMap();
+
+ // Map (String name -> SignatureGenerator)
+ private Map signatureGenerators = new HashMap();
// List (Trigger)
private List triggers = new ArrayList();
@@ -684,6 +688,19 @@ public class IvySettings implements Sort
public void addConfigured(ModuleDescriptorParser parser) {
ModuleDescriptorParserRegistry.getInstance().addParser(parser);
}
+
+ public void addConfigured(SignatureGenerator generator) {
+ addSignatureGenerator(generator);
+ }
+
+ public void addSignatureGenerator(SignatureGenerator generator) {
+ init(generator);
+ signatureGenerators.put(generator.getName(), generator);
+ }
+
+ public SignatureGenerator getSignatureGenerator(String name) {
+ return (SignatureGenerator) signatureGenerators.get(name);
+ }
public void addResolver(DependencyResolver resolver) {
if (resolver == null) {
Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/XmlSettingsParser.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/XmlSettingsParser.java?rev=991108&r1=991107&r2=991108&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/XmlSettingsParser.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/XmlSettingsParser.java Tue Aug 31 07:47:06 2010
@@ -107,7 +107,7 @@ public class XmlSettingsParser extends D
private List configuratorTags = Arrays.asList(new String[] {"resolvers", "namespaces",
"parsers", "latest-strategies", "conflict-managers", "outputters", "version-matchers",
"statuses", "circular-dependency-strategies", "triggers", "lock-strategies",
- "caches"});
+ "caches", "signers"});
private IvySettings ivy;
Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/typedef.properties
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/typedef.properties?rev=991108&r1=991107&r2=991108&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/typedef.properties (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/typedef.properties Tue Aug 31 07:47:06 2010
@@ -54,4 +54,6 @@ ant-build = org.apache.ivy.ant.AntBuild
ant-call = org.apache.ivy.ant.AntCallTrigger
log = org.apache.ivy.plugins.trigger.LogTrigger
-cache = org.apache.ivy.core.cache.DefaultRepositoryCacheManager
\ No newline at end of file
+cache = org.apache.ivy.core.cache.DefaultRepositoryCacheManager
+
+pgp = org.apache.ivy.plugins.signer.bouncycastle.OpenPGPSignatureGenerator
\ No newline at end of file
Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/resolver/RepositoryResolver.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/resolver/RepositoryResolver.java?rev=991108&r1=991107&r2=991108&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/resolver/RepositoryResolver.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/resolver/RepositoryResolver.java Tue Aug 31 07:47:06 2010
@@ -45,6 +45,7 @@ import org.apache.ivy.plugins.repository
import org.apache.ivy.plugins.resolver.util.ResolvedResource;
import org.apache.ivy.plugins.resolver.util.ResolverHelper;
import org.apache.ivy.plugins.resolver.util.ResourceMDParser;
+import org.apache.ivy.plugins.signer.SignatureGenerator;
import org.apache.ivy.plugins.version.VersionMatcher;
import org.apache.ivy.util.ChecksumHelper;
import org.apache.ivy.util.FileUtil;
@@ -58,6 +59,8 @@ public class RepositoryResolver extends
private Repository repository;
private Boolean alwaysCheckExactRevision = null;
+
+ private String signerName = null;
public RepositoryResolver() {
}
@@ -76,6 +79,10 @@ public class RepositoryResolver extends
((AbstractRepository) repository).setName(name);
}
}
+
+ public void setSigner(String signerName) {
+ this.signerName = signerName;
+ }
protected ResolvedResource findResourceUsingPattern(ModuleRevisionId mrid, String pattern,
Artifact artifact, ResourceMDParser rmdparser, Date date) {
@@ -223,11 +230,15 @@ public class RepositoryResolver extends
throw new IllegalArgumentException("Unknown checksum algorithm: " + checksums[i]);
}
}
-
+
repository.put(artifact, src, dest, overwrite);
for (int i = 0; i < checksums.length; i++) {
putChecksum(artifact, src, dest, overwrite, checksums[i]);
}
+
+ if (signerName != null) {
+ putSignature(artifact, src, dest, overwrite);
+ }
}
protected void putChecksum(Artifact artifact, File src, String dest, boolean overwrite,
@@ -243,6 +254,25 @@ public class RepositoryResolver extends
}
}
+ protected void putSignature(Artifact artifact, File src, String dest, boolean overwrite) throws IOException {
+ SignatureGenerator gen = getSettings().getSignatureGenerator(signerName);
+ if (gen == null) {
+ throw new IllegalArgumentException("Couldn't sign the artifacts! " +
+ "Unknown signer name: '" + signerName + "'");
+ }
+
+ File tempFile = File.createTempFile("ivytemp", gen.getExtension());
+
+ try {
+ gen.sign(src, tempFile);
+ repository.put(DefaultArtifact.cloneWithAnotherTypeAndExt(artifact,
+ gen.getExtension(), artifact.getExt() + "." + gen.getExtension()),
+ tempFile, dest + "." + gen.getExtension(), overwrite);
+ } finally {
+ tempFile.delete();
+ }
+ }
+
public DownloadReport download(Artifact[] artifacts, DownloadOptions options) {
EventManager eventManager = getEventManager();
try {
Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/resolver/ResolverSettings.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/resolver/ResolverSettings.java?rev=991108&r1=991107&r2=991108&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/resolver/ResolverSettings.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/resolver/ResolverSettings.java Tue Aug 31 07:47:06 2010
@@ -24,6 +24,7 @@ import org.apache.ivy.core.module.id.Mod
import org.apache.ivy.plugins.latest.LatestStrategy;
import org.apache.ivy.plugins.namespace.Namespace;
import org.apache.ivy.plugins.parser.ParserSettings;
+import org.apache.ivy.plugins.signer.SignatureGenerator;
import org.apache.ivy.plugins.version.VersionMatcher;
public interface ResolverSettings extends ParserSettings {
@@ -51,5 +52,7 @@ public interface ResolverSettings extend
String getResolveMode(ModuleId moduleId);
void filterIgnore(Collection names);
+
+ SignatureGenerator getSignatureGenerator(String name);
}
Added: ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/signer/SignatureGenerator.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/signer/SignatureGenerator.java?rev=991108&view=auto
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/signer/SignatureGenerator.java (added)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/signer/SignatureGenerator.java Tue Aug 31 07:47:06 2010
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ivy.plugins.signer;
+
+import java.io.File;
+import java.io.IOException;
+
+public interface SignatureGenerator {
+
+ String getName();
+
+ void sign(File src, File dest) throws IOException;
+
+ String getExtension();
+
+}
Added: ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/signer/bouncycastle/OpenPGPSignatureGenerator.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/signer/bouncycastle/OpenPGPSignatureGenerator.java?rev=991108&view=auto
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/signer/bouncycastle/OpenPGPSignatureGenerator.java (added)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/signer/bouncycastle/OpenPGPSignatureGenerator.java Tue Aug 31 07:47:06 2010
@@ -0,0 +1,176 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ivy.plugins.signer.bouncycastle;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Security;
+import java.security.SignatureException;
+import java.util.Iterator;
+
+import org.apache.ivy.plugins.signer.SignatureGenerator;
+import org.bouncycastle.bcpg.ArmoredOutputStream;
+import org.bouncycastle.bcpg.BCPGOutputStream;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openpgp.PGPException;
+import org.bouncycastle.openpgp.PGPPrivateKey;
+import org.bouncycastle.openpgp.PGPSecretKey;
+import org.bouncycastle.openpgp.PGPSecretKeyRing;
+import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
+import org.bouncycastle.openpgp.PGPSignature;
+import org.bouncycastle.openpgp.PGPSignatureGenerator;
+import org.bouncycastle.openpgp.PGPUtil;
+
+public class OpenPGPSignatureGenerator implements SignatureGenerator {
+
+ private static final long MASK = 0xFFFFFFFFL;
+
+ static {
+ Security.addProvider(new BouncyCastleProvider());
+ }
+
+ private String name;
+ private String secring;
+ private String password;
+ private String keyId;
+
+ private PGPSecretKey pgpSec;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getExtension() {
+ return "asc";
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public void setSecring(String secring) {
+ this.secring = secring;
+ }
+
+ public void setKeyId(String keyId) {
+ if (!"auto".equals(keyId)) {
+ this.keyId = keyId;
+ }
+ }
+
+ public void sign(File src, File dest) throws IOException {
+ OutputStream out = null;
+ InputStream in = null;
+ InputStream keyIn = null;
+
+ try {
+ if (secring == null) {
+ secring = System.getProperty("user.home") + "/.gnupg/secring.gpg";
+ }
+
+ if (pgpSec == null) {
+ keyIn = new FileInputStream(secring);
+ pgpSec = readSecretKey(keyIn);
+ }
+
+ PGPPrivateKey pgpPrivKey = pgpSec.extractPrivateKey(password.toCharArray(), BouncyCastleProvider.PROVIDER_NAME);
+ PGPSignatureGenerator sGen = new PGPSignatureGenerator(pgpSec.getPublicKey().getAlgorithm(), PGPUtil.SHA1, BouncyCastleProvider.PROVIDER_NAME);
+ sGen.initSign(PGPSignature.BINARY_DOCUMENT, pgpPrivKey);
+
+ in = new FileInputStream(src);
+ out = new BCPGOutputStream(new ArmoredOutputStream(new FileOutputStream(dest)));
+
+ int ch = 0;
+ while ((ch = in.read()) >= 0) {
+ sGen.update((byte) ch);
+ }
+
+ sGen.generate().encode(out);
+ } catch (SignatureException e) {
+ IOException ioexc = new IOException();
+ ioexc.initCause(e);
+ throw ioexc;
+ } catch (PGPException e) {
+ IOException ioexc = new IOException();
+ ioexc.initCause(e);
+ throw ioexc;
+ } catch (NoSuchAlgorithmException e) {
+ IOException ioexc = new IOException();
+ ioexc.initCause(e);
+ throw ioexc;
+ } catch (NoSuchProviderException e) {
+ IOException ioexc = new IOException();
+ ioexc.initCause(e);
+ throw ioexc;
+ } finally {
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException e) {}
+ }
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {}
+ }
+ if (keyIn != null) {
+ try {
+ keyIn.close();
+ } catch (IOException e) {}
+ }
+ }
+ }
+
+ private PGPSecretKey readSecretKey(InputStream in) throws IOException, PGPException {
+ in = PGPUtil.getDecoderStream(in);
+ PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(in);
+
+ PGPSecretKey key = null;
+ for (Iterator it = pgpSec.getKeyRings(); key == null && it.hasNext(); ) {
+ PGPSecretKeyRing kRing = (PGPSecretKeyRing) it.next();
+
+ for (Iterator it2 = kRing.getSecretKeys(); key == null && it2.hasNext(); ) {
+ PGPSecretKey k = (PGPSecretKey) it2.next();
+ if ((keyId == null) && k.isSigningKey()) {
+ key = k;
+ }
+ if ((keyId != null) && (Long.valueOf(keyId, 16).longValue() == (k.getKeyID() & MASK))) {
+ key = k;
+ }
+ }
+ }
+
+ if (key == null) {
+ throw new IllegalArgumentException("Can't find encryption key" +
+ (keyId != null ? " '" + keyId + "' " : " ") + "in key ring.");
+ }
+
+ return key;
+ }
+
+}