| /* |
| * 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 |
| * |
| * https://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.Security; |
| 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; |
| import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor; |
| import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator; |
| import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder; |
| import org.bouncycastle.openpgp.operator.bc.BcPGPContentSignerBuilder; |
| import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider; |
| |
| 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); |
| } |
| |
| PBESecretKeyDecryptor decryptor = new BcPBESecretKeyDecryptorBuilder( |
| new BcPGPDigestCalculatorProvider()).build(password.toCharArray()); |
| PGPPrivateKey pgpPrivKey = pgpSec.extractPrivateKey(decryptor); |
| PGPSignatureGenerator sGen = new PGPSignatureGenerator(new BcPGPContentSignerBuilder( |
| pgpSec.getPublicKey().getAlgorithm(), PGPUtil.SHA1)); |
| sGen.init(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 (PGPException e) { |
| throw new IOException(e); |
| } 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, |
| new BcKeyFingerprintCalculator()); |
| |
| PGPSecretKey key = null; |
| Iterator<PGPSecretKeyRing> it = pgpSec.getKeyRings(); |
| while (key == null && it.hasNext()) { |
| PGPSecretKeyRing kRing = it.next(); |
| |
| Iterator<PGPSecretKey> it2 = kRing.getSecretKeys(); |
| while (key == null && it2.hasNext()) { |
| PGPSecretKey k = it2.next(); |
| if (keyId == null && k.isSigningKey()) { |
| key = k; |
| } |
| if (keyId != null && Long.valueOf(keyId, 16) == (k.getKeyID() & MASK)) { |
| key = k; |
| } |
| } |
| } |
| |
| if (key == null) { |
| throw new IllegalArgumentException("Can't find encryption key" |
| + (keyId != null ? " '" + keyId + "' " : " ") + "in key ring."); |
| } |
| |
| return key; |
| } |
| |
| } |