PageRenderTime 79ms CodeModel.GetById 35ms app.highlight 31ms RepoModel.GetById 1ms app.codeStats 0ms

/src/org/jgroups/auth/X509Token.java

https://github.com/jadahl/jgroups-android
Java | 245 lines | 189 code | 31 blank | 25 comment | 40 complexity | 51a331f96a31688d3ff1909a53266be3 MD5 | raw file
Possible License(s): LGPL-2.1
  1package org.jgroups.auth;
  2
  3import org.jgroups.util.Util;
  4import org.jgroups.Message;
  5
  6import javax.crypto.Cipher;
  7import java.io.*;
  8import java.util.Properties;
  9import java.security.cert.X509Certificate;
 10import java.security.PrivateKey;
 11import java.security.KeyStore;
 12/**
 13 * <p>
 14 * This is an example of using a preshared token that is encrypted using an X509 certificate for authentication purposes.  All members of the group have to have the same string value in the JGroups config.
 15 * </p>
 16 * <p>
 17 * This example uses certificates contained within a specified keystore.  Configuration parameters for this example are shown below:
 18 * </p>
 19 * <ul>
 20 *  <li>keystore_type = JKS(default)/PKCS12 - see http://java.sun.com/j2se/1.4.2/docs/guide/security/CryptoSpec.html#AppA</li>
 21 *  <li>keystore_path (required) = the location of the keystore</li>
 22 *  <li>keystore_password (required) =  the password of the keystore</li>
 23 *  <li>cert_alias (required) = the alias of the certification within the keystore</li>
 24 *  <li>cert_password = the password of the certification within the keystore</li>
 25 *  <li>auth_value (required) = the string to encrypt</li>
 26 *  <li>cipher_type = RSA(default)/AES/Blowfish/DES/DESede/PBEWithMD5AndDES/PBEWithHmacSHA1AndDESede/RC2/RC4/RC5 - see http://java.sun.com/j2se/1.4.2/docs/guide/security/jce/JCERefGuide.html#AppA</li>
 27 * </ul>
 28 * @see org.jgroups.auth.AuthToken
 29 * @author Chris Mills
 30 */
 31public class X509Token extends AuthToken {
 32
 33    public static final String KEYSTORE_TYPE = "keystore_type";
 34    public static final String KEYSTORE_PATH = "keystore_path";
 35    public static final String KEYSTORE_PASSWORD = "keystore_password";
 36    public static final String CERT_ALIAS = "cert_alias";
 37    public static final String CERT_PASSWORD = "cert_password";
 38    public static final String TOKEN_ATTR = "auth_value";
 39    public static final String CIPHER_TYPE = "cipher_type";
 40
 41    private boolean valueSet = false;
 42
 43    private String keystore_type = null;
 44    private String cert_alias = null;
 45    private String keystore_path = null;
 46    private String token_attr = null;
 47    private String cipher_type = null;
 48
 49    private byte[] encryptedToken = null;
 50
 51    private char[] cert_password = null;
 52    private char[] keystore_password = null;
 53
 54    private Cipher cipher = null;
 55    private PrivateKey certPrivateKey = null;
 56    private X509Certificate certificate = null;
 57
 58    public X509Token() {
 59        //need an empty constructor
 60    }
 61
 62    public void setValue(Properties properties) {
 63        if(log.isDebugEnabled()){
 64            log.debug("setting values on X509Token object");
 65        }
 66
 67        if(properties.containsKey(TOKEN_ATTR)){
 68            this.token_attr = (String) properties.get(TOKEN_ATTR);
 69            properties.remove(TOKEN_ATTR);
 70            if(log.isDebugEnabled()){
 71                log.debug("token_attr = " + this.token_attr);
 72            }
 73        }
 74
 75        if(properties.containsKey(KEYSTORE_TYPE)){
 76            this.keystore_type = (String) properties.get(KEYSTORE_TYPE);
 77            properties.remove(KEYSTORE_TYPE);
 78            if(log.isDebugEnabled()){
 79                log.debug("keystore_type = " + this.keystore_type);
 80            }
 81        }else{
 82            this.keystore_type = "JKS";
 83            if(log.isDebugEnabled()){
 84                log.debug("keystore_type = " + this.keystore_type);
 85            }
 86        }
 87
 88        if(properties.containsKey(KEYSTORE_PATH)){
 89            this.keystore_path = (String) properties.get(KEYSTORE_PATH);
 90            properties.remove(KEYSTORE_PATH);
 91            if(log.isDebugEnabled()){
 92                log.debug("keystore_path = " + this.keystore_path);
 93            }
 94        }
 95
 96        if(properties.containsKey(KEYSTORE_PASSWORD)){
 97            this.keystore_password = ((String) properties.get(KEYSTORE_PASSWORD)).toCharArray();
 98            properties.remove(KEYSTORE_PASSWORD);
 99            if(log.isDebugEnabled()){
100                log.debug("keystore_password = " + this.keystore_password);
101            }
102        }
103
104        if(properties.containsKey(CERT_ALIAS)){
105            this.cert_alias = (String) properties.get(CERT_ALIAS);
106            properties.remove(CERT_ALIAS);
107            if(log.isDebugEnabled()){
108                log.debug("cert_alias = " + this.cert_alias);
109            }
110        }
111
112        if(properties.containsKey(CERT_PASSWORD)){
113            this.cert_password = ((String) properties.get(CERT_PASSWORD)).toCharArray();
114            properties.remove(CERT_PASSWORD);
115            if(log.isDebugEnabled()){
116                log.debug("cert_password = " + this.cert_password);
117            }
118        }else{
119            this.cert_password = this.keystore_password;
120            if(log.isDebugEnabled()){
121                log.debug("cert_password = " + this.cert_password);
122            }
123        }
124
125        if(properties.containsKey(CIPHER_TYPE)){
126            this.cipher_type = (String) properties.get(CIPHER_TYPE);
127            properties.remove(CIPHER_TYPE);
128            if(log.isDebugEnabled()){
129                log.debug("cipher_type = " + this.cipher_type);
130            }
131        }else{
132            this.cipher_type = "RSA";
133            if(log.isDebugEnabled()){
134                log.debug("cipher_type = " + this.cipher_type);
135            }
136        }
137
138        if(getCertificate()){
139            this.valueSet = true;
140            if(log.isDebugEnabled()){
141                log.debug("X509Token created correctly");
142            }
143        }
144    }
145
146    public String getName() {
147        return "org.jgroups.auth.X509Token";
148    }
149
150    public boolean authenticate(AuthToken token, Message msg) {
151        if (!this.valueSet) {
152            if(log.isFatalEnabled()){
153                log.fatal("X509Token not setup correctly - check token attrs");
154            }
155            return false;
156        }
157
158        if((token != null) && (token instanceof X509Token)){
159            //got a valid X509 token object
160            X509Token serverToken = (X509Token)token;
161            if(!serverToken.valueSet){
162                if(log.isFatalEnabled()){
163                    log.fatal("X509Token - recieved token not valid");
164                }
165                return false;
166            }
167
168            try{
169                if(log.isDebugEnabled()){
170                    log.debug("setting cipher to decrypt mode");
171                }
172                this.cipher.init(Cipher.DECRYPT_MODE, this.certPrivateKey);
173                String serverBytes = new String(this.cipher.doFinal(serverToken.encryptedToken));
174                if((serverBytes != null) && (serverBytes.equalsIgnoreCase(this.token_attr))){
175                    if(log.isDebugEnabled()){
176                        log.debug("X509 authentication passed");
177                    }
178                    return true;
179                }
180            }catch(Exception e){
181                if(log.isFatalEnabled()){
182                    log.fatal(e);
183                }
184            }
185        }
186        if(log.isWarnEnabled()){
187            log.warn("X509 authentication failed");
188        }
189        return false;
190    }
191
192    public void writeTo(DataOutputStream out) throws IOException {
193        if(log.isDebugEnabled()){
194            log.debug("X509Token writeTo()");
195        }
196        Util.writeByteBuffer(this.encryptedToken, out);
197    }
198
199    public void readFrom(DataInputStream in) throws IOException, IllegalAccessException, InstantiationException {
200        if(log.isDebugEnabled()){
201            log.debug("X509Token readFrom()");
202        }
203        this.encryptedToken = Util.readByteBuffer(in);
204        this.valueSet = true;
205    }
206    /**
207     * Used during setup to get the certification from the keystore and encrypt the auth_value with the private key
208     * @return true if the certificate was found and the string encypted correctly otherwise returns false
209     */
210    private boolean getCertificate() {
211        try{
212            KeyStore store = KeyStore.getInstance(this.keystore_type);
213            java.io.FileInputStream fis = new java.io.FileInputStream(this.keystore_path);
214            store.load(fis, this.keystore_password);
215
216            this.cipher = Cipher.getInstance(this.cipher_type);
217            this.certificate = (X509Certificate) store.getCertificate(this.cert_alias);
218
219            if(log.isDebugEnabled()){
220                log.debug("certificate = " + this.certificate.toString());
221            }
222
223            this.cipher.init(Cipher.ENCRYPT_MODE, this.certificate);
224            this.encryptedToken = this.cipher.doFinal(this.token_attr.getBytes());
225
226            if(log.isDebugEnabled()){
227                log.debug("encryptedToken = " + this.encryptedToken);
228            }
229
230            KeyStore.PrivateKeyEntry privateKey = (KeyStore.PrivateKeyEntry)store.getEntry(this.cert_alias, new KeyStore.PasswordProtection(this.cert_password));
231            this.certPrivateKey = privateKey.getPrivateKey();
232
233            if(log.isDebugEnabled()){
234                log.debug("certPrivateKey = " + this.certPrivateKey.toString());
235            }
236
237            return true;
238        }catch(Exception e){
239            if(log.isFatalEnabled()){
240                log.fatal(e);
241            }
242            return false;
243        }
244    }
245}