PageRenderTime 58ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://github.com/jiwils/JGroups
Java | 202 lines | 133 code | 31 blank | 38 comment | 18 complexity | a8a94a4e92c35283e031660d7ab8e552 MD5 | raw file
  1. package org.jgroups.auth;
  2. import java.io.DataInput;
  3. import java.io.DataOutput;
  4. import java.io.IOException;
  5. import java.security.InvalidKeyException;
  6. import java.security.KeyStore;
  7. import java.security.KeyStoreException;
  8. import java.security.NoSuchAlgorithmException;
  9. import java.security.PrivateKey;
  10. import java.security.UnrecoverableEntryException;
  11. import java.security.cert.CertificateException;
  12. import java.security.cert.X509Certificate;
  13. import javax.crypto.BadPaddingException;
  14. import javax.crypto.Cipher;
  15. import javax.crypto.IllegalBlockSizeException;
  16. import javax.crypto.NoSuchPaddingException;
  17. import org.jgroups.Message;
  18. import org.jgroups.annotations.Property;
  19. import org.jgroups.util.Util;
  20. /**
  21. * <p>
  22. * This is an example of using a preshared token that is encrypted using an X509 certificate for
  23. * authentication purposes. All members of the group have to have the same string value in the
  24. * JGroups config.
  25. * </p>
  26. * <p>
  27. * This example uses certificates contained within a specified keystore. Configuration parameters
  28. * for this example are shown below:
  29. * </p>
  30. * <ul>
  31. * <li>keystore_type = JKS(default)/PKCS12 - see
  32. * http://java.sun.com/j2se/1.4.2/docs/guide/security/CryptoSpec.html#AppA</li>
  33. * <li>keystore_path (required) = the location of the keystore</li>
  34. * <li>keystore_password (required) = the password of the keystore</li>
  35. * <li>cert_alias (required) = the alias of the certification within the keystore</li>
  36. * <li>cert_password = the password of the certification within the keystore</li>
  37. * <li>auth_value (required) = the string to encrypt</li>
  38. * <li>cipher_type =
  39. * RSA(default)/AES/Blowfish/DES/DESede/PBEWithMD5AndDES/PBEWithHmacSHA1AndDESede/RC2/RC4/RC5 - see
  40. * http://java.sun.com/j2se/1.4.2/docs/guide/security/jce/JCERefGuide.html#AppA</li>
  41. * </ul>
  42. *
  43. * @author Chris Mills
  44. * @see org.jgroups.auth.AuthToken
  45. */
  46. public class X509Token extends AuthToken {
  47. public static final String KEYSTORE_TYPE = "keystore_type";
  48. public static final String KEYSTORE_PATH = "keystore_path";
  49. public static final String KEYSTORE_PASSWORD = "keystore_password";
  50. public static final String CERT_ALIAS = "cert_alias";
  51. public static final String CERT_PASSWORD = "cert_password";
  52. public static final String TOKEN_ATTR = "auth_value";
  53. public static final String CIPHER_TYPE = "cipher_type";
  54. private boolean valueSet = false;
  55. @Property
  56. private String keystore_type = "JKS";
  57. @Property
  58. private String cert_alias = null;
  59. @Property
  60. private String keystore_path = null;
  61. @Property
  62. private String auth_value = null;
  63. @Property
  64. private String cipher_type = "RSA";
  65. private byte[] encryptedToken = null;
  66. private char[] cert_password = null;
  67. private char[] keystore_password = null;
  68. private Cipher cipher = null;
  69. private PrivateKey certPrivateKey = null;
  70. private X509Certificate certificate = null;
  71. public X509Token() {
  72. // need an empty constructor
  73. }
  74. @Property(name = "cert_password")
  75. public void setCertPassword(String pwd) {
  76. this.cert_password = pwd.toCharArray();
  77. }
  78. @Property(name = "keystore_password")
  79. public void setKeyStorePassword(String pwd) {
  80. this.keystore_password = pwd.toCharArray();
  81. if (cert_password == null)
  82. cert_password = keystore_password;
  83. }
  84. public String getName() {
  85. return "org.jgroups.auth.X509Token";
  86. }
  87. public boolean authenticate(AuthToken token, Message msg) {
  88. if (!this.valueSet) {
  89. if (log.isFatalEnabled()) {
  90. log.fatal("X509Token not setup correctly - check token attrs");
  91. }
  92. return false;
  93. }
  94. if ((token != null) && (token instanceof X509Token)) {
  95. // got a valid X509 token object
  96. X509Token serverToken = (X509Token) token;
  97. if (!serverToken.valueSet) {
  98. if (log.isFatalEnabled()) {
  99. log.fatal("X509Token - recieved token not valid");
  100. }
  101. return false;
  102. }
  103. try {
  104. if (log.isDebugEnabled()) {
  105. log.debug("setting cipher to decrypt mode");
  106. }
  107. this.cipher.init(Cipher.DECRYPT_MODE, this.certPrivateKey);
  108. String serverBytes = new String(this.cipher.doFinal(serverToken.encryptedToken));
  109. if ((serverBytes.equalsIgnoreCase(this.auth_value))) {
  110. if (log.isDebugEnabled()) {
  111. log.debug("X509 authentication passed");
  112. }
  113. return true;
  114. }
  115. } catch (Exception e) {
  116. if (log.isFatalEnabled()) {
  117. log.fatal(e.toString());
  118. }
  119. }
  120. }
  121. // if(log.isWarnEnabled()){
  122. // log.warn("X509 authentication failed");
  123. // }
  124. return false;
  125. }
  126. public void writeTo(DataOutput out) throws IOException {
  127. if (log.isDebugEnabled()) {
  128. log.debug("X509Token writeTo()");
  129. }
  130. Util.writeByteBuffer(this.encryptedToken, out);
  131. }
  132. public void readFrom(DataInput in) throws IOException, IllegalAccessException,
  133. InstantiationException {
  134. if (log.isDebugEnabled()) {
  135. log.debug("X509Token readFrom()");
  136. }
  137. this.encryptedToken = Util.readByteBuffer(in);
  138. this.valueSet = true;
  139. }
  140. /**
  141. * Used during setup to get the certification from the keystore and encrypt the auth_value with
  142. * the private key
  143. *
  144. * @return true if the certificate was found and the string encypted correctly otherwise returns
  145. * false
  146. */
  147. public void setCertificate() throws KeyStoreException, IOException, NoSuchAlgorithmException,
  148. CertificateException, NoSuchPaddingException, InvalidKeyException,
  149. IllegalBlockSizeException, BadPaddingException, UnrecoverableEntryException {
  150. KeyStore store = KeyStore.getInstance(this.keystore_type);
  151. java.io.FileInputStream fis = new java.io.FileInputStream(this.keystore_path);
  152. store.load(fis, this.keystore_password);
  153. this.cipher = Cipher.getInstance(this.cipher_type);
  154. this.certificate = (X509Certificate) store.getCertificate(this.cert_alias);
  155. if (log.isDebugEnabled()) {
  156. log.debug("certificate = " + this.certificate.toString());
  157. }
  158. this.cipher.init(Cipher.ENCRYPT_MODE, this.certificate);
  159. this.encryptedToken = this.cipher.doFinal(this.auth_value.getBytes());
  160. if (log.isDebugEnabled()) {
  161. log.debug("encryptedToken = " + this.encryptedToken);
  162. }
  163. KeyStore.PrivateKeyEntry privateKey = (KeyStore.PrivateKeyEntry) store.getEntry(
  164. this.cert_alias, new KeyStore.PasswordProtection(this.cert_password));
  165. this.certPrivateKey = privateKey.getPrivateKey();
  166. this.valueSet=true;
  167. if (log.isDebugEnabled()) {
  168. log.debug("certPrivateKey = " + this.certPrivateKey.toString());
  169. }
  170. }
  171. }