Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
697 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
SMIME and Resteasy | ||
======================== | ||
This example shows how to use SMIME over HTTP to encrypt and/or sign message bodies. The examples use keys and certificates | ||
generated by the 'openssl' command-line utility that is available on most unix-based systems as well as installable | ||
on Windows. If you're doing pure Java, then its fine to use the Java keytool and KeyStore facilities to manage your keys/certificates. | ||
The example also has python clients to show how different languages interacting. This is why we chose to use openssl | ||
to generate our keys/certificates. | ||
|
||
The pem files private.pem and cert.pem were generated with this command: | ||
|
||
$ openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout private.pem -out cert.pem | ||
|
||
|
||
There are two ways to run the example: | ||
|
||
$ mvn install | ||
|
||
This builds, runs the WAR, and then invokes all the Java tests. This basically shows Java to Java communication | ||
passing back and forth SMIME messages over HTTP | ||
|
||
|
||
The second way is to run the WAR and interact with Python clients: | ||
|
||
1. mvn jetty:run | ||
|
||
This starts the web server in interaction mode | ||
|
||
|
||
2. Run one of the python clients | ||
|
||
$ python getEncrypted.py | ||
$ python getSigned.py | ||
$ python postEncrypted.py | ||
$ python postSigned.py | ||
$ python getEncryptedSigned.py | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import httplib, urlparse | ||
from M2Crypto import BIO, SMIME, X509 | ||
|
||
conn = httplib.HTTPConnection("localhost:9095") | ||
conn.request("GET", "/smime/encrypted") | ||
res = conn.getresponse() | ||
if res.status != 200: | ||
print res.status | ||
raise Exception("Failed to connect") | ||
|
||
contentType = res.getheader("content-type") | ||
data = res.read() | ||
|
||
# Need to reconstruct a Mail message with content type | ||
# as SMIME wants it in that format | ||
bio = BIO.MemoryBuffer("Content-Type: ") | ||
bio.write(contentType) | ||
bio.write("\r\n\r\n") | ||
bio.write(data) | ||
|
||
s = SMIME.SMIME() | ||
s.load_key('src/main/resources/private.pem', 'src/main/resources/cert.pem') | ||
|
||
p7, d = SMIME.smime_load_pkcs7_bio(bio) | ||
out = s.decrypt(p7) | ||
|
||
print "--- Received Data ---" | ||
# It may contain headers like Content-Type, so you'll have to parse it | ||
print out |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import httplib, urlparse | ||
from M2Crypto import BIO, SMIME, X509 | ||
|
||
conn = httplib.HTTPConnection("localhost:9095") | ||
conn.request("GET", "/smime/encrypted/signed") | ||
res = conn.getresponse() | ||
if res.status != 200: | ||
print res.status | ||
raise Exception("Failed to connect") | ||
|
||
contentType = res.getheader("content-type") | ||
data = res.read() | ||
|
||
# Need to reconstruct a Mail message with content type | ||
# as SMIME wants it in that format | ||
bio = BIO.MemoryBuffer("Content-Type: ") | ||
bio.write(contentType) | ||
bio.write("\r\n\r\n") | ||
bio.write(data) | ||
|
||
s = SMIME.SMIME() | ||
s.load_key('src/main/resources/private.pem', 'src/main/resources/cert.pem') | ||
|
||
p7, d = SMIME.smime_load_pkcs7_bio(bio) | ||
out = s.decrypt(p7) | ||
|
||
|
||
|
||
# Load the signer's cert. | ||
x509 = X509.load_cert('src/main/resources/cert.pem') | ||
sk = X509.X509_Stack() | ||
sk.push(x509) | ||
s.set_x509_stack(sk) | ||
|
||
# Load the signer's CA cert. In this case, because the signer's | ||
# cert is self-signed, it is the signer's cert itself. | ||
st = X509.X509_Store() | ||
st.load_info('src/main/resources/cert.pem') | ||
s.set_x509_store(st) | ||
|
||
# Recall 'out' contains a PKCS #7 blob. | ||
# Transform 'out'; verify the resulting PKCS #7 blob. | ||
p7_bio = BIO.MemoryBuffer(out) | ||
p7, data = SMIME.smime_load_pkcs7_bio(p7_bio) | ||
v = s.verify(p7, data) | ||
|
||
print v | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import httplib, urlparse | ||
from M2Crypto import BIO, SMIME, X509 | ||
|
||
conn = httplib.HTTPConnection("localhost:9095") | ||
conn.request("GET", "/smime/signed") | ||
res = conn.getresponse() | ||
if res.status != 200: | ||
print res.status | ||
raise Exception("Failed to connect") | ||
|
||
contentType = res.getheader("content-type") | ||
data = res.read() | ||
|
||
# Need to reconstruct a Mail message with content type | ||
# as SMIME wants it in that format | ||
bio = BIO.MemoryBuffer("Content-Type: ") | ||
bio.write(contentType) | ||
bio.write("\r\n\r\n") | ||
bio.write(data) | ||
|
||
s = SMIME.SMIME() | ||
|
||
# Load the signer's cert. | ||
x509 = X509.load_cert('src/main/resources/cert.pem') | ||
sk = X509.X509_Stack() | ||
sk.push(x509) | ||
s.set_x509_stack(sk) | ||
|
||
# Load the signer's CA cert. In this case, because the signer's | ||
# cert is self-signed, it is the signer's cert itself. | ||
st = X509.X509_Store() | ||
st.load_info('src/main/resources/cert.pem') | ||
s.set_x509_store(st) | ||
|
||
# Load the data, verify it. | ||
p7, data = SMIME.smime_load_pkcs7_bio(bio) | ||
v = s.verify(p7, data) | ||
print v |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
<parent> | ||
<groupId>org.jboss.resteasy</groupId> | ||
<artifactId>digital-signatures</artifactId> | ||
<version>3.0.10.Final</version> | ||
<relativePath>../pom.xml</relativePath> | ||
</parent> | ||
<modelVersion>4.0.0</modelVersion> | ||
<groupId>org.jboss.resteasy.test</groupId> | ||
<artifactId>smime-example</artifactId> | ||
<packaging>war</packaging> | ||
<name>smime-example</name> | ||
<description/> | ||
<url>http://maven.apache.org</url> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>junit</groupId> | ||
<artifactId>junit</artifactId> | ||
<version>${dep.junit.version}</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.jboss.resteasy</groupId> | ||
<artifactId>resteasy-jaxrs</artifactId> | ||
<version>${dep.resteasy.version}</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.jboss.resteasy</groupId> | ||
<artifactId>resteasy-client</artifactId> | ||
<version>${dep.resteasy.version}</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.jboss.resteasy</groupId> | ||
<artifactId>resteasy-crypto</artifactId> | ||
<version>${dep.resteasy.version}</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.jboss.resteasy</groupId> | ||
<artifactId>resteasy-jaxb-provider</artifactId> | ||
<version>${dep.resteasy.version}</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<finalName>smime</finalName> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.wildfly.plugins</groupId> | ||
<artifactId>wildfly-maven-plugin</artifactId> | ||
<version>1.1.0.Alpha1</version> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-surefire-plugin</artifactId> | ||
<version>2.17</version> | ||
<configuration> | ||
<skip>true</skip> | ||
</configuration> | ||
<executions> | ||
<execution> | ||
<id>surefire-it</id> | ||
<phase>integration-test</phase> | ||
<goals> | ||
<goal>test</goal> | ||
</goals> | ||
<configuration> | ||
<skip>false</skip> | ||
</configuration> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-compiler-plugin</artifactId> | ||
<version>3.1</version> | ||
<configuration> | ||
<source>1.6</source> | ||
<target>1.6</target> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import httplib, urlparse | ||
from M2Crypto import BIO, Rand, SMIME, X509 | ||
|
||
# Make a MemoryBuffer of the message. | ||
buf = BIO.MemoryBuffer( | ||
"""Content-Type: application/xml | ||
<customer name="bill"/> | ||
""") | ||
|
||
# Seed the PRNG. | ||
Rand.load_file('randpool.dat', -1) | ||
|
||
# Instantiate an SMIME object. | ||
s = SMIME.SMIME() | ||
|
||
# Load target cert to encrypt to. | ||
x509 = X509.load_cert('src/main/resources/cert.pem') | ||
sk = X509.X509_Stack() | ||
sk.push(x509) | ||
s.set_x509_stack(sk) | ||
|
||
# Set cipher: 3-key triple-DES in CBC mode. | ||
s.set_cipher(SMIME.Cipher('des_ede3_cbc')) | ||
|
||
# Encrypt the buffer. | ||
p7 = s.encrypt(buf) | ||
|
||
out = BIO.MemoryBuffer() | ||
s.write(out, p7) | ||
|
||
# Strip out junk, I can't figure out a better way to do this | ||
# This is kind of a hack, but I couldn't figure out how to just | ||
# get the body without the headers, or just send the BIO directly thru the HTTP connection | ||
# s.write(out, py) adds a bunch of headers and doesn't just output the body | ||
# so, I read 5 lines then use the rest of the buffer to initalize the string | ||
|
||
out.readline() | ||
out.readline() | ||
out.readline() | ||
out.readline() | ||
out.readline() | ||
o = out.read() | ||
|
||
# This is an alternative way to extract the body | ||
#p7.write(out) | ||
#o = out.read() | ||
#o = o.replace('-----BEGIN PKCS7-----', '') | ||
#o = o.replace('-----END PKCS7-----', '') | ||
#o = o.strip() | ||
|
||
# Finally send the message | ||
conn = httplib.HTTPConnection("localhost:9095") | ||
headers = {"Content-Disposition" : "attachment; filename=\"smime.p7m\"", | ||
"Content-Type" : "application/pkcs7-mime; smime-type=enveloped-data; name=\"smime.p7m\"", | ||
"Content-Transfer-Encoding" :"base64"} | ||
|
||
|
||
conn.request("POST", "/smime/encrypted", o, headers) | ||
res = conn.getresponse() | ||
print res.status, res.reason | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import httplib, urlparse | ||
import re | ||
from M2Crypto import BIO, Rand, SMIME, X509 | ||
|
||
|
||
data = """Content-Type: application/xml | ||
<customer name="bill"/> | ||
""" | ||
# Make a MemoryBuffer of the message. | ||
|
||
|
||
buf = BIO.MemoryBuffer(data) | ||
|
||
# Seed the PRNG. | ||
Rand.load_file('randpool.dat', -1) | ||
|
||
# Instantiate an SMIME object. | ||
s = SMIME.SMIME() | ||
s.load_key('src/main/resources/private.pem', 'src/main/resources/cert.pem') | ||
p7 = s.sign(buf, SMIME.PKCS7_DETACHED) | ||
|
||
out = BIO.MemoryBuffer() | ||
buf = BIO.MemoryBuffer(data) | ||
s.write(out, p7, buf) | ||
|
||
# Extract the content-type and multipart message. I can't figure out a better way to do this | ||
# This is kind of a hack, but I couldn't figure out how to just | ||
# get the body and headers separately or just send the BIO directly thru the HTTP connection | ||
l = out.readline() | ||
l = out.readline() | ||
|
||
result = re.match('Content-Type: (.*)', l) | ||
contentType = result.group(1) | ||
|
||
l = out.readline() | ||
l = out.readline() | ||
|
||
o = out.read() | ||
|
||
# Finally send the message | ||
conn = httplib.HTTPConnection("localhost:9095") | ||
headers = {"Content-Type" : contentType} | ||
|
||
|
||
conn.request("POST", "/smime/signed", o, headers) | ||
res = conn.getresponse() | ||
print res.status, res.reason | ||
|
Oops, something went wrong.