1 package org.apache.commons.openpgp;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import org.bouncycastle.bcpg.ArmoredOutputStream;
21 import org.bouncycastle.bcpg.BCPGOutputStream;
22 import org.bouncycastle.bcpg.HashAlgorithmTags;
23 import org.bouncycastle.jce.provider.BouncyCastleProvider;
24 import org.bouncycastle.openpgp.PGPException;
25 import org.bouncycastle.openpgp.PGPPrivateKey;
26 import org.bouncycastle.openpgp.PGPSecretKey;
27 import org.bouncycastle.openpgp.PGPSignature;
28 import org.bouncycastle.openpgp.PGPSignatureGenerator;
29 import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
30 import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
31 import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
32
33 import java.io.ByteArrayOutputStream;
34 import java.io.IOException;
35 import java.io.OutputStream;
36 import java.security.Security;
37 import java.security.SignatureException;
38
39
40
41
42
43
44 public class BouncyCastleOpenPgpStreamingSigner
45 implements OpenPgpStreamingSigner
46 {
47 private static final String PROVIDER = "BC";
48
49 private PGPSignatureGenerator sGen;
50
51 private final ByteArrayOutputStream signatureBytes;
52
53 private BCPGOutputStream bOut;
54
55 public BouncyCastleOpenPgpStreamingSigner( String keyId, KeyRing keyRing, boolean asciiArmor )
56 throws OpenPgpException
57 {
58 signatureBytes = new ByteArrayOutputStream();
59 init( asciiArmor, signatureBytes, keyRing, keyId );
60 }
61
62 public BouncyCastleOpenPgpStreamingSigner( OutputStream signature, String keyId, KeyRing keyRing,
63 boolean asciiArmor )
64 throws OpenPgpException
65 {
66 signatureBytes = null;
67 init( asciiArmor, signature, keyRing, keyId );
68 }
69
70 private void init( boolean asciiArmor, OutputStream signature, KeyRing keyRing, String keyId )
71 throws OpenPgpException
72 {
73
74 Security.addProvider( new BouncyCastleProvider() );
75
76 OutputStream out;
77 if ( asciiArmor )
78 {
79 out = new ArmoredOutputStream( signature );
80 }
81 else
82 {
83 out = signature;
84 }
85 bOut = new BCPGOutputStream( out );
86
87 try
88 {
89 PGPSecretKey pgpSec = keyRing.getSecretKey( keyId );
90 if ( pgpSec == null )
91 {
92 throw new OpenPgpException( "The key with id '" + keyId + "' was not found in the secret keyring." );
93 }
94 PGPPrivateKey pgpPrivKey = pgpSec.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder(
95 new JcaPGPDigestCalculatorProviderBuilder().setProvider(PROVIDER).build()).setProvider(PROVIDER).
96 build(keyRing.getPassword()));
97 sGen = new PGPSignatureGenerator(new JcaPGPContentSignerBuilder(pgpSec.getPublicKey().getAlgorithm(),
98 HashAlgorithmTags.SHA1).setProvider(PROVIDER).setDigestProvider(PROVIDER));
99 sGen.init(PGPSignature.BINARY_DOCUMENT, pgpPrivKey);
100 }
101 catch ( PGPException e )
102 {
103
104 throw new OpenPgpException( "Error calculating detached signature", e );
105 }
106 }
107
108 public void update( byte[] buf )
109 throws OpenPgpException
110 {
111 update( buf, 0, buf.length );
112 }
113
114 public void update( byte[] buf, int offset, int length )
115 throws OpenPgpException
116 {
117 try
118 {
119 sGen.update( buf, offset, length );
120 }
121 catch ( SignatureException e )
122 {
123
124 throw new OpenPgpException( "Error calculating detached signature", e );
125 }
126 }
127
128 public byte[] finish()
129 throws OpenPgpException, IOException
130 {
131 try
132 {
133 sGen.generate().encode( bOut );
134 }
135 catch ( PGPException e )
136 {
137
138 throw new OpenPgpException( "Error calculating detached signature", e );
139 }
140 catch ( SignatureException e )
141 {
142
143 throw new OpenPgpException( "Error calculating detached signature", e );
144 }
145 bOut.close();
146 return signatureBytes != null ? signatureBytes.toByteArray() : null;
147 }
148 }