001    package org.apache.commons.openpgp;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one or more
005     * contributor license agreements.  See the NOTICE file distributed with
006     * this work for additional information regarding copyright ownership.
007     * The ASF licenses this file to You under the Apache License, Version 2.0
008     * (the "License"); you may not use this file except in compliance with
009     * the License.  You may obtain a copy of the License at
010     *
011     *      http://www.apache.org/licenses/LICENSE-2.0
012     *
013     * Unless required by applicable law or agreed to in writing, software
014     * distributed under the License is distributed on an "AS IS" BASIS,
015     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016     * See the License for the specific language governing permissions and
017     * limitations under the License.
018     */
019    
020    import java.io.IOException;
021    import java.io.InputStream;
022    import java.util.HashMap;
023    import java.util.Map;
024    
025    import org.bouncycastle.openpgp.PGPException;
026    import org.bouncycastle.openpgp.PGPObjectFactory;
027    import org.bouncycastle.openpgp.PGPPublicKey;
028    import org.bouncycastle.openpgp.PGPPublicKeyRing;
029    import org.bouncycastle.openpgp.PGPSecretKey;
030    import org.bouncycastle.openpgp.PGPSecretKeyRing;
031    import org.bouncycastle.openpgp.PGPUtil;
032    
033    /**
034     * Bouncy Castle implementation of the OpenPGP key ring.
035     * 
036     * @author <a href="mailto:brett@apache.org">Brett Porter</a>
037     * @todo password is not secure
038     */
039    public class BouncyCastleKeyRing implements KeyRing
040    {
041        private String firstKeyId;
042    
043        private final Map<Long, PGPSecretKey> pgpSec = new HashMap<Long, PGPSecretKey>();
044    
045        private char[] password;
046    
047        private final Map<Long, PGPPublicKey> pgpPub = new HashMap<Long, PGPPublicKey>();
048    
049        private static final long MASK = 0xFFFFFFFFL;
050    
051        public BouncyCastleKeyRing()
052        {
053        }
054        
055        public BouncyCastleKeyRing( InputStream secretKeyRingStream, InputStream publicKeyRingStream, char[] password )
056            throws IOException, PGPException
057        {
058            addSecretKeyRing( secretKeyRingStream, password );
059    
060            addPublicKeyRing( publicKeyRingStream );
061        }
062    
063        public void addPublicKeyRing( InputStream publicKeyRingStream )
064            throws IOException, PGPException
065        {
066            PGPObjectFactory pgpFact = new PGPObjectFactory( PGPUtil.getDecoderStream( publicKeyRingStream ) );
067            Object obj;
068    
069            while ( ( obj = pgpFact.nextObject() ) != null )
070            {
071                if ( !( obj instanceof PGPPublicKeyRing ) )
072                {
073                    throw new PGPException( obj.getClass().getName() + " found where PGPPublicKeyRing expected" );
074                }
075    
076                PGPPublicKeyRing keyRing = (PGPPublicKeyRing) obj;
077                long key = keyRing.getPublicKey().getKeyID() & MASK;
078    
079                pgpPub.put( key, keyRing.getPublicKey() );
080            }
081        }
082    
083        public void addSecretKeyRing( InputStream secretKeyRingStream, char[] password )
084            throws IOException, PGPException
085        {
086            PGPObjectFactory pgpFact = new PGPObjectFactory( PGPUtil.getDecoderStream( secretKeyRingStream ) );
087            Object obj;
088    
089            while ( ( obj = pgpFact.nextObject() ) != null )
090            {
091                if ( !( obj instanceof PGPSecretKeyRing ) )
092                {
093                    throw new PGPException( obj.getClass().getName() + " found where PGPSecretKeyRing expected" );
094                }
095    
096                PGPSecretKeyRing pgpSecret = (PGPSecretKeyRing) obj;
097                long key = pgpSecret.getSecretKey().getKeyID() & MASK;
098                if ( pgpSec.isEmpty() )
099                {
100                    // Convert the keyId to a hexadecimal upper case String
101                    firstKeyId = Long.toHexString( key ).toUpperCase();
102                }
103    
104                pgpSec.put( key, pgpSecret.getSecretKey() );
105            }
106    
107            this.password = password;
108        }
109    
110        public String getFirstKeyId()
111        {
112            return firstKeyId.toString();
113        }
114    
115        public char[] getPassword()
116        {
117            return password;
118        }
119    
120        public PGPSecretKey getSecretKey( String keyId )
121        {
122            return pgpSec.get( Long.valueOf( keyId, 16 ) );
123        }
124    
125        public PGPPublicKey getPublicKey( String keyId )
126        {
127            return pgpPub.get( Long.valueOf( keyId, 16 ) );
128        }
129    
130        public PGPSecretKey getSecretKey( long keyId )
131        {
132            return pgpSec.get(keyId & MASK);
133        }
134    
135        public PGPPublicKey getPublicKey( long keyId )
136        {
137            return pgpPub.get(keyId & MASK);
138        }
139    }