abdera-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jmsn...@apache.org
Subject svn commit: r482390 - in /incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/servlet: DHContext.java DHEncryptedResponseFilter.java
Date Mon, 04 Dec 2006 22:21:33 GMT
Author: jmsnell
Date: Mon Dec  4 14:21:32 2006
New Revision: 482390

URL: http://svn.apache.org/viewvc?view=rev&rev=482390
Log:
Add a Diffie-Hellman Encrypted Response Filter. See the javadocs for details

Added:
    incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/servlet/DHContext.java
    incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/servlet/DHEncryptedResponseFilter.java

Added: incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/servlet/DHContext.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/servlet/DHContext.java?view=auto&rev=482390
==============================================================================
--- incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/servlet/DHContext.java
(added)
+++ incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/servlet/DHContext.java
Mon Dec  4 14:21:32 2006
@@ -0,0 +1,210 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  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
+*
+*     http://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.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.abdera.security.util.servlet;
+
+import java.math.BigInteger;
+import java.security.AlgorithmParameterGenerator;
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.spec.InvalidParameterSpecException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
+
+import javax.crypto.KeyAgreement;
+import javax.crypto.spec.DHParameterSpec;
+
+import org.apache.abdera.security.Encryption;
+import org.apache.abdera.security.EncryptionOptions;
+import org.apache.axiom.om.util.Base64;
+import org.apache.xml.security.encryption.XMLCipher;
+
+/**
+ * Implements the Diffie-Hellman Key Exchange details for both parties
+ * 
+ * Party A:
+ * 
+ * DHContext context_a = new DHContext();
+ * String req = context_a.getRequestString();
+ * 
+ * Party B:
+ * 
+ * DHContext context_b = new DHContext(req);
+ * EncryptionOptions options = context_b.getEncryptionOptions(enc);
+ * // encrypt
+ * String ret = context_b.getResponseString();
+ * 
+ * Party A:
+ * 
+ * context_a.setPublicKey(ret);
+ * EncryptionOptions options = context_a.getEncryptionOptions(enc);
+ * // decrypt
+ * 
+ */
+public class DHContext {
+
+  BigInteger p = null, g = null;
+  int l = 0;
+  private KeyPair keyPair;
+  private Key publicKey;
+  
+  public DHContext() {
+    try {
+      init();
+    } catch (Exception e) {}
+  }
+  
+  public DHContext(String dh) {
+    try {
+      init(dh);
+    } catch (Exception e) {}
+  }
+  
+  public String getRequestString() {
+    StringBuffer buf = new StringBuffer();
+    buf.append("p=");
+    buf.append(p.toString());
+    buf.append(", ");
+    buf.append("g=");
+    buf.append(g.toString());
+    buf.append(", ");
+    buf.append("l=");
+    buf.append(l);
+    buf.append(", ");
+    buf.append("k=");
+    buf.append(Base64.encode(keyPair.getPublic().getEncoded()));
+    return buf.toString();
+  }
+  
+  public String getResponseString() {
+    StringBuffer buf = new StringBuffer();
+    buf.append("k=");
+    buf.append(Base64.encode(keyPair.getPublic().getEncoded()));
+    return buf.toString();
+  }
+  
+  private void init() 
+    throws NoSuchAlgorithmException, 
+           InvalidAlgorithmParameterException, 
+           InvalidParameterSpecException,
+           InvalidKeySpecException  {
+    AlgorithmParameterGenerator pgen = AlgorithmParameterGenerator.getInstance("DH");
+    pgen.init(512);
+    AlgorithmParameters params = pgen.generateParameters();
+    DHParameterSpec dhspec = (DHParameterSpec)params.getParameterSpec(DHParameterSpec.class);
+    KeyPairGenerator keypairgen = KeyPairGenerator.getInstance("DH");
+    keypairgen.initialize(dhspec);   
+    keyPair = keypairgen.generateKeyPair();
+    p = dhspec.getP();
+    g = dhspec.getG();
+    l = dhspec.getL();
+  }
+  
+  private void init(
+    String dh) 
+      throws NoSuchAlgorithmException, 
+             InvalidAlgorithmParameterException, 
+             InvalidKeySpecException {
+    String[] params = dh.split("\\s*,\\s*");
+    byte[] key = null;
+    for (String param : params) {
+      String name = param.substring(0,param.indexOf("="));
+      String value = param.substring(param.indexOf("=") + 1);
+      if (name.equalsIgnoreCase("p"))
+        p = new BigInteger(value);
+      else if (name.equalsIgnoreCase("g"))
+        g = new BigInteger(value);
+      else if (name.equalsIgnoreCase("l"))
+        l = Integer.parseInt(value);
+      else if (name.equalsIgnoreCase("k"))
+        key = Base64.decode(value);
+    }
+    init(p,g,l,key);
+  }
+  
+  private void init(
+    BigInteger p, 
+    BigInteger g, 
+    int l, 
+    byte[] key) 
+      throws NoSuchAlgorithmException, 
+             InvalidAlgorithmParameterException, 
+             InvalidKeySpecException {
+    DHParameterSpec spec = new DHParameterSpec(p,g,l);
+    KeyPairGenerator keypairgen = KeyPairGenerator.getInstance("DH");
+    keypairgen.initialize(spec);   
+    keyPair = keypairgen.generateKeyPair();
+    publicKey = decode(key);
+  }
+  
+  public KeyPair getKeyPair() {
+    return keyPair;
+  }
+  
+  public Key getPublicKey() {
+    return publicKey;
+  }
+  
+  private Key decode(
+    byte[] key)      
+      throws NoSuchAlgorithmException, 
+             InvalidKeySpecException {
+    X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
+    KeyFactory keyFact = KeyFactory.getInstance("DH");
+    return keyFact.generatePublic(x509KeySpec);
+  }
+  
+  public void setPublicKey(
+    String dh) 
+      throws NoSuchAlgorithmException, 
+             InvalidKeySpecException {
+    String[] tokens = dh.split("\\s*,\\s*");
+    byte[] key = null;
+    for (String token : tokens) {
+      String name = token.substring(0,token.indexOf("="));
+      String value = token.substring(token.indexOf("=") + 1);
+      if (name.equalsIgnoreCase("k"))
+        key = Base64.decode(value);
+    }
+    publicKey = decode(key);
+  }
+  
+  public Key generateSecret() 
+    throws NoSuchAlgorithmException, 
+           InvalidKeyException {
+    KeyAgreement ka = KeyAgreement.getInstance("DH");
+    ka.init(keyPair.getPrivate());
+    ka.doPhase(publicKey, true);
+    return ka.generateSecret("DESede");
+  }
+  
+  public EncryptionOptions getEncryptionOptions(
+    Encryption enc) 
+      throws InvalidKeyException, 
+             NoSuchAlgorithmException {
+    EncryptionOptions options = enc.getDefaultEncryptionOptions();
+    options.setDataEncryptionKey(generateSecret());
+    options.setDataCipherAlgorithm(XMLCipher.TRIPLEDES);
+    return options;
+  }
+}

Added: incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/servlet/DHEncryptedResponseFilter.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/servlet/DHEncryptedResponseFilter.java?view=auto&rev=482390
==============================================================================
--- incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/servlet/DHEncryptedResponseFilter.java
(added)
+++ incubator/abdera/java/trunk/security/src/main/java/org/apache/abdera/security/util/servlet/DHEncryptedResponseFilter.java
Mon Dec  4 14:21:32 2006
@@ -0,0 +1,136 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  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
+*
+*     http://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.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.abdera.security.util.servlet;
+
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Security;
+import java.security.spec.InvalidKeySpecException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.abdera.model.Document;
+import org.apache.abdera.model.Element;
+import org.apache.abdera.security.Encryption;
+import org.apache.abdera.security.EncryptionOptions;
+
+/**
+ * A Servlet Filter that uses Diffie-Hellman Key Exchange to encrypt 
+ * Atom documents.  The HTTP request must include a X-DH header in the form:
+ * 
+ * X-DH: p={dh_p}, g={dh_g}, l={dh_l}, k={base64_pubkey}
+ * 
+ * Example Client Code:
+ * <pre>
+ *   DHContext context = new DHContext();
+ *   Abdera abdera = new Abdera();
+ *   CommonsClient client = new CommonsClient(abdera);
+ *   RequestOptions options = client.getDefaultRequestOptions();
+ *   options.setHeader("X-DH", context.getRequestString());
+ *   
+ *   ClientResponse response = client.get("http://localhost:8080/TestWeb/test",options);
+ *   Document<Element> doc = response.getDocument();
+ *   
+ *   String dh_ret = response.getHeader("X-DH");
+ *   if (dh_ret != null) {
+ *     context.setPublicKey(dh_ret);
+ *     AbderaSecurity absec = new AbderaSecurity(abdera);
+ *     Encryption enc = absec.getEncryption();
+ *     EncryptionOptions encoptions = context.getEncryptionOptions(enc);
+ *     doc = enc.decrypt(doc, encoptions);
+ *   }
+ *   
+ *   doc.writeTo(System.out);
+ * </pre>
+ * 
+ * Webapp Deployment:
+ * <pre>
+ * &lt;filter>
+ *   &lt;filter-name>enc filter&lt;/filter-name>
+ *   &lt;filter-class>com.test.EncryptedResponseFilter&lt;/filter-class>
+ * &lt;/filter>
+ * &lt;filter-mapping>
+ *   &lt;filter-name>enc filter&lt;/filter-name>
+ *   &lt;servlet-name>TestServlet&lt;/servlet-name>
+ * &lt;/filter-mapping>
+ * </pre>
+ */
+public class DHEncryptedResponseFilter 
+  extends SecurityFilter {
+
+  public void init(
+    FilterConfig config) 
+      throws ServletException {
+    try {
+      Class.forName("org.bouncycastle.LICENSE");
+      Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
+    } catch (Exception e) {}
+  }
+  
+  @SuppressWarnings("unchecked")
+  public void doFilter(
+    ServletRequest request, 
+    ServletResponse response,
+    FilterChain chain) 
+      throws IOException, 
+             ServletException {
+    try {
+      DHContext context = getDHContext((HttpServletRequest)request);
+      if (context != null) {
+        BufferingResponseWrapper wrapper = 
+          new BufferingResponseWrapper(
+            (HttpServletResponse)response);
+        chain.doFilter(request, wrapper);
+        Document<Element> doc = getDocument(wrapper);
+        if (doc != null) {  
+          Encryption enc = security.getEncryption(); 
+          EncryptionOptions options = context.getEncryptionOptions(enc);
+          Document<Element> enc_doc = enc.encrypt(doc, options);
+          returnPublicKey((HttpServletResponse)response,context);
+          enc_doc.writeTo(response.getOutputStream());
+        }
+      } else {
+        chain.doFilter(request, response);
+      }
+    } catch (Exception e) {}
+  } 
+  
+  private void returnPublicKey(HttpServletResponse response, DHContext context) {
+    response.setHeader("X-DH",context.getResponseString());
+  }
+  
+  private DHContext getDHContext(HttpServletRequest request) 
+    throws InvalidAlgorithmParameterException, 
+           NoSuchAlgorithmException, 
+           InvalidKeySpecException {
+    String dh_req = request.getHeader("X-DH");
+    if (dh_req == null || dh_req.length() == 0) return null;
+    DHContext context = new DHContext(dh_req);
+    return context;
+  }
+  
+}
+
+



Mime
View raw message