Skip to main content

Signing, encrypting, and decrypting Atom

Abdera meets Java cryptography

Nicholas Chase has been involved in Web site development for companies such as Lucent Technologies, Sun Microsystems, Oracle, and the Tampa Bay Buccaneers. Nick has been a high school physics teacher, a low-level radioactive waste facility manager, an online science fiction magazine editor, a multimedia engineer, an Oracle instructor, and the Chief Technology Officer of an interactive communications company. He is the author of several books, including XML Primer Plus (Sams).

Summary:  Atom is a great format for relaying information, but what about security concerns? XML Digital Signatures can ensure that data comes from a trusted party and that it is unaltered, and XML Encryption can obscure sensitive information from prying eyes. But how can you use these technologies without destroying Atom structures? This article shows you how digital signatures and encryption can easily mesh with Atom data using the Apache Abdera API.

Date:  22 May 2007
Level:  Intermediate
Activity:  1410 views
Comments:  

Getting ready

This article assumes that you are familiar with the concepts behind the Atom syndication format. You should also have at least a passing familiarity with the concepts behind XML security, though this isn't strictly necessary.

To follow along with the examples, you will need to download Apache Abdera, a package that eases the manipulation of Atom data, from http://incubator.apache.org/abdera/. You'll also need to download Apache's XML Security implementation from http://xml.apache.org/security/download.html. To set up your environment, add all of the *.jar file from both packages to your classpath.


What this article is about

Because Atom data generally travels over HTTP on the Web, it's impossible to completely ignore potential security concerns. For example, with syndicated content that is displayed in places other than its point of origin (the whole point of syndication, after all!) how can you tell that one of the parties involved didn't alter the data? And what about sensitive data meant only for a single individual or organization? Banking information is, of course, the most obvious. Would you want to receive your bank information through a raw HTTP feed? The issue applies to any sensitive information, such as internal company information.

This article shows you how to use digital signatures and encryption to solve these problems.


The (very) quick encryption refresher

Remember when you were a kid and you had a secret code you shared with your friends? You could make up messages and encrypt them, and your friend could use the code to decode the message. He could also use the code to create a message that you could read. This is an example of shared key encryption, because you both have the same code.

Now, this works great to just obscure the content of a message from prying eyes, and you'll see how to use shared key encryption to do just that in a few moments.

But, shared key encryption has a small problem. If you received an encoded message that tells you to attack the girls club house with snowballs, how would you know that it really came from your friend, and not the neighborhood bully trying to get you in trouble? And if you sent a message to your friend, how would you guarantee that he and only he could read it?

In the grown-up world, you solve these problems through the use of public key-private key encryption. There's not one key, but a key pair. What is locked, so to speak, by one can only be unlocked by the other, and vice versa.

One key is kept private, and the other is publicly associated with its owner. Going back to the childhood example, your friend could encrypt the attack plans using his private key. If his public key successfully decrypted it, you know the plans came from him. Of course, since his public key is, well, public, anyone can read the message. On the other hand, he could use your public key to encrypt the message, which means only your private key can be used to read it. That solves the security problem, but not the authentication issue.

The real world solves these problems with a combination of the two techniques. For example, messages can be digitally signed. This process enables you to determine both who sent the message and whether it changed en route. Combine that with straight out encryption and all of your problems are solved.

Let's start simply, by just encrypting Atom entries.


Encrypting an Atom entry

Consider a typical Atom entry, like those you might find on a blog (see Listing 1).


Listing 1. A sample entry
                
<?xml version='1.0' encoding='utf-8'?>
<entry xmlns="http://www.w3.org/2005/Atom">
  <id>urn:EncryptionExample/3263827</id>
  <author>
    <name>Nick Chase</name>
  </author>
  <title type="text">Apache Abdera eases Atom</title>
  <content type="text">
    Tired of making raw HTTP calls?  Now you can use a new 
package from Apache ...
  </content>
  <link href="http://incubator.apache.org/abdera/" />
  <updated>2007-03-20T12:43:26.687Z</updated>
</entry>

This is just a simple XML document, but Abdera enables you to represent it as an object (see Listing 2).


Listing 2. The entry as an object
                
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

import org.apache.abdera.Abdera;
import org.apache.abdera.factory.Factory;
import org.apache.abdera.model.*;
import org.apache.abdera.security.*;

public class EncryptionDemo {

  public static void main(String[] args) throws Exception {

    Abdera abdera = new Abdera();
    Factory factory = abdera.getFactory();

    Entry entry = factory.newEntry();
    entry.setId("urn:EncryptionExample/3263827");
    entry.addAuthor("Nick Chase");
    entry.setTitle("Apache Abdera eases Atom");
    entry.setContent("Tired of making raw HTTP calls?  Now "+
    		         "you can use a new package from Apache ...");
    entry.addLink("http://incubator.apache.org/abdera/");
    entry.setUpdated(new java.util.Date());

    entry.writeTo(System.out);
  }
}

This code creates the XML shown in Listing 1. First, create the Abdera object, which provides most of the functionality you will need. (The security functions are mostly within the AbderaSecurity class.) The Abdera object provides the Factory, which can create entries or other objects. Once you have the object, you can set its properties. Conveniently, the Entry object provides an easy way to serialize itself to the command line or other OutputStream.

The advantage to representing the entry as an object is that you can then programmatically encrypt it (see Listing 3).


Listing 3. Encrypting the entry
                
...
    entry.setUpdated(new java.util.Date());

    KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
    keyGenerator.init(128);
    SecretKey secretKey = keyGenerator.generateKey();

    AbderaSecurity abderaSec = new AbderaSecurity(abdera);
    Encryption encryption = abderaSec.getEncryption();
    EncryptionOptions options = encryption.getDefaultEncryptionOptions();
    options.setDataEncryptionKey(secretKey);
    Document<Element> encryptedDoc = 
                    encryption.encrypt(entry.getDocument(), options);

    encryptedDoc.writeTo(System.out);
        
  }

}

The first step is to create the key you'll use to encrypt the message. To do that, you'll need a KeyGenerator object. You can specify various encryption algorithms, such as Data Encryption Standard (DES) and RSA, but Advanced Encryption Standard (AES) is included with the default installation of Java™ 1.5 environment. Here you set a key size of 128 bits. Once you generate the key, you can use the AbderaSecurity class to get an Encryption object and feed it the key you just created. From there, you can simply encrypt the entry.

You should then see results similar to listing 4.


Listing 4. The encrypted entry
                
<?xml version='1.0' encoding='utf-8'?>
<xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" 
Type="http://www.w3.org/2001/04/xmlenc#Element"><xenc:EncryptionMethod 
Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" 
/><xenc:CipherData><xenc:CipherValue>SWy9qLh7wwvAY2t/hhlC4kwGCuknc0Ml7aVm/B
+kHZOkLb8Y7tQQ6pUvHBzmQTak075MTsjLgtWW
lg/XH6RawbBUWiP3tLdHvI/S6rpgNyQFUKBv1CiG4mmFNktewu/FG5fZQMaqj3AtkQffyg4KLA+Q
WXLD7Gbl4gvj9sUrmCBDDZs6U60aPNOManD6Bb0OppiFZdCvrvYQZ0yoLzISEnf46L+oEo56+FId
5HHCilfvQb66DDhCHYl7NNR3ofF2P8Pg9eg1jWD4/ZGctCWuxWmQgPfdmJGJf+zsZwFCLfLmJWuL
iARc16MrdMIFbKAgk61neyrco3fkQPhbTGvCK8wWOr2wHpzlAJAxrLX+TSpzqQ7jcWtX4VR07Sg0
ymnMNvBCNWHUZeckswoTCUu78ujs/p51M8/csZSwg4ZUCcSf47wEm54rDJngaPPT31b8xeqVNxgS
6eh/hwbcAiR/rf1LeeJz2KvcXI27aCmU5BT2wxxzRIHrpKiiExFhydCOFi+1WlOdzML6ghSjvxAo
+gCd1b2zDX29t9AuvZ0I+zo=</xenc:CipherValue></xenc:CipherData>
</xenc:EncryptedData>

You can even create a feed of these encrypted entries (see Listing 5).


Listing 5. A feed of encrypted entries
                
...
    Document<Element> encryptedDoc = 
                encryption.encrypt(entry.getDocument(), options);

    encryptedDoc.writeTo(System.out);

    Entry entry2 = factory.newEntry();
    entry2.setId("urn:EncryptionExample/3263827");
    entry2.addAuthor("Nick Chase");
    entry2.setTitle("And you can use encryption, too");
    entry2.setContent("Abdera enables you to encrypt data.");
    entry2.addLink("http://incubator.apache.org/abdera/");
    entry2.setUpdated(new java.util.Date());
    Document<Element> encryptedDoc2 = 
               encryption.encrypt(entry2.getDocument(), options);

    Feed feed = factory.newFeed();
    feed.addAuthor("Nick Chase");
    feed.addComment("These entries are encrypted using AES.");

    Entry encEntry = factory.newEntry();
    encEntry.setContent(encryptedDoc.getRoot());
    feed.addEntry(encEntry);

    Entry encEntry2 = factory.newEntry();
    encEntry2.addExtension(encryptedDoc2.getRoot());
    feed.addEntry(encEntry2);

    feed.writeTo(System.out);

  }

}

In this case, you create another entry just to make things interesting. From there, create a new feed and provide its basic information. Next, create an empty entry and set its contents as the element representing the encrypted entry. You can then add the populated entry to the feed. This listing also contains an example of adding the data as an extension to the entry rather than as content.

This represents just two ways to create a feed of encrypted data. You could, of course, encrypt the entire feed as a whole using the same techniques. In this case, however, you should see results similar to Listing 6 (spacing added for clarity).


Listing 6. The feed of encrypted entries
                
<feed xmlns="http://www.w3.org/2005/Atom">
   <author>
      <name>Nick Chase</name>
   </author>
   <!--These entries are encrypted using AES.-->
   <entry>
      <content type="application/xml">
        <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" 
                Type="http://www.w3.org/2001/04/xmlenc#Element">
          <xenc:EncryptionMethod 
               Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" />
          <xenc:CipherData>
             <xenc:CipherValue>SLbTBADt8Dh2wS3LN7KLUyNCyzHFy4giwHwrmoEI4Z20M
xrk+PSpU6ekldF9k2qPxYiE5zVAS5E2
MxZOfV8M6CofAqP9/OeK16YBfP20+JyzEjdGChpQ3HqDo8lclfNOCTT0xmZY9+foGqmpEXyBquxU
KDV9Yk7jq77TcGyrh50hbjrprg5O3+Htv2w+CSZNRr+ruB76p2wFT/gI1WHOqCg6CQCQ/EF+fMxY
iYWLEVJ8wfrqjJytD4hy0xqSemMEedUo65qYl7rJuAsaABvKyiaspQNz/LEIeAkOpUC0aJqa1ERU
ju/vRe/bVfC49cHsoUoYEOxcCF/KQxfC7wypeEJIyT99tDSgLMWKD1OpnI4g2JvIF9DqZFdnxpBH
vAnlujs/2nj2JGyUxzQQb+e+YHcGlXeuTFZHlgwXwuBev8yxN842EJsGDtx++712hB+SRex+Rifu
b0028qaRYETrXZX9hK7gmCEQGsbjXWYawKl0In/P/iMmVaoi3R3UKPJ8Dcdu/67Ukyr8AouquaTG
cWGGcxtliaK67q/NeBL+fFk=</xenc:CipherValue>
          </xenc:CipherData>
        </xenc:EncryptedData>
      </content>
   </entry>
   <entry xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
     <xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element">
        <xenc:EncryptionMethod 
                  Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" />
        <xenc:CipherData>
           <xenc:CipherValue>JkgXKRwpjfcjqd8VweZuoMhtxK4wu1uJZLBLhRlDOz7t
/+uHlxmjtzBYf0/izRo2NEO3ZYFhB9GF
021N8HfnA0ZGh+2MS/FfQfqnSc0DsxzzxlKSEKFNIEcmpRzyrMVNE6kLVMicWgGJrm5t9ZcXXyZ4
TRDKcFWGMjS3PEgd8KpCi0NYt8bAVxxNooGp7o8B7CiPZbgmjYYjo7WgP8l66auS7ciTZLoaEj3j
jpmQyl0l1cGgAbCaBK2/hvfek7W6M1vkoLCCXZIr28cmeAfOT189i1+TrtZoOU8+xXYhHbPGlJG2
5GAMyM89OpAy8psOrjEnxipF/04okKrULmmSeWA2QvqJsUAA4KtbmKQODLaac/eSJAp1eLikhBIW
2GsfsVvmdO0yqNI96n8oY761yE6+1KEGpFohnIi7Zv5Xp7nI8jfXlFSnyiJaDiP/GxVC6MznnTdw
iUqk8yxMak9fxLDBjRO6+VJHDPXZtPybnQ+3SJjKOxLUVFJmNP7sXO1P</xenc:CipherValue>
        </xenc:CipherData>
     </xenc:EncryptedData>
   </entry>
</feed>

And, of course, what gets encrypted must be decrypted (see Listing 7).


Listing 7. Decrypting entries
                
...
Document<Entry> decryptedEntry = 
    	 encryption.decrypt(encryptedDoc, options);
decryptedEntry.writeTo(System.out);
...

In this case, you use the same object to decrypt the content that you used to encrypt it. You should see the original entry as a result.

That seems simple enough. But what about signing entries?


Getting ready for digital signatures

Before you can do anything with digital signatures, you need to create a key pair, a public key and a private key. With this pair, you can not only encrypt a message, but also create a certificate. A certificate is a digital file that includes a person's (or an entity's) public key and other information such as a name and serial number. In the real world, the certificates are typically themselves signed by some trusted authority such as VeriSign or an internal entity so you know that the public key is legitimate.

In these examples, you'll use a self-signed certificate.


Generating keys

Fortunately, all of the tools you need to create key pairs are part of the standard Java implementation. Specifically, you'll need the keytool application, which you can find in JAVA_HOME/bin. To create a keystore, the file that holds the keys, as well as the initial key pair, execute the following command (see Listing 8).


Listing 8. Creating a keystore
                
keytool -genkey -alias nick -keypass nickpass -keystore c:/sw/newkeystore.jks -storepass
nickKeyStorePass

You should, of course, substitute your own values!

This creates a file that includes the key pair and is password protected. To make things easier, place the keystore file in the same directory as your Java class.


Signing in entry

Now that you have your key pair, you can go ahead and sign the entry (see Listing 9).


Listing 9. Sign the entry
                
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;

import org.apache.abdera.Abdera;
import org.apache.abdera.factory.Factory;
import org.apache.abdera.model.Document;
import org.apache.abdera.model.Entry;
import org.apache.abdera.security.AbderaSecurity;
import org.apache.abdera.security.Signature;
import org.apache.abdera.security.SignatureOptions;
import org.apache.abdera.model.Entry;

public class DigitalSignatureDemo {

  public static void main(String[] args) throws Exception {

    Abdera abdera = new Abdera();
    Factory factory = abdera.getFactory();

    Entry entry = factory.newEntry();
    entry.setId("urn:EncryptionExample/3263827");
    entry.addAuthor("Nick Chase");
    entry.setTitle("Apache Abdera eases Atom");
    entry.setContent("Tired of making raw HTTP calls?  Now "+
    		                "you can use a new package from Apache ...");
    entry.addLink("http://incubator.apache.org/abdera/");
    entry.setUpdated(new java.util.Date());

    KeyStore keystore = KeyStore.getInstance("JKS");
    InputStream keyStream = 
         DigitalSignatureDemo.class.getResourceAsStream("newkeystore.jks");
    keystore.load(keyStream, new String("nickKeyStorePass").toCharArray());

    PrivateKey privateKey = (PrivateKey)keystore.getKey(
        "nick", new String("nickpass").toCharArray());

    X509Certificate certificate = (X509Certificate)keystore.getCertificate("nick");

    AbderaSecurity abderaSec = new AbderaSecurity(abdera);
    Signature signature = abderaSec.newSignature();
    SignatureOptions options = signature.getDefaultSignatureOptions();    
    options.setSigningKey(privateKey);
    options.setCertificate(certificate);
    entry = signature.sign(entry, options);
    entry.writeTo(System.out);    

  }

}

Once you have the entry design, the first step is to load the KeyStore as an object so you can retrieve data from it. To do that, you'll need to load the stream and the password you added to the key store when you created it. (That is the storepass parameter.)

After you have the keystore, extract the private key using the alias you assigned it. You'll use it to encrypt the digest, essentially a hash of the entry. By doing this, you provide a way to prove that you are the one who signed the entry. If your public key can decrypt the entry, then your private key was used to sign it. Of course, you'll need to provide your public key to verify that. Your public key is part of your certificate, which you'll retrieve next using the same alias as your private key.

Next, use the AbderaSecurity class to obtain a Signature object. You'll use that object to sign the entry, but first you need to provide it with both the private key and the certificate to use. Once you set those options, simply sign the entry.

This process adds the digital signature to the entry, as you can see in Listing 10.


Listing 10. A signed entry
                
<entry xmlns="http://www.w3.org/2005/Atom">
  <id>urn:EncryptionExample/3263827</id>
  <author>
    <name>Nick Chase</name>
  </author>
  <title type="text">Apache Abdera eases Atom</title>
  <content type="text">Tired of making raw HTTP calls?  Now you can 
use a new package from Apache ...</content>
  <link href="http://incubator.apache.org/abdera/" />
  <updated>2007-03-21T13:23:18.812Z</updated>
  <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <ds:SignedInfo>
      <ds:CanonicalizationMethod 
         Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
      <ds:SignatureMethod 
              Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
      <ds:Reference URI="">
        <ds:Transforms>
          <ds:Transform Algorithm=
             "http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
          <ds:Transform 
                 Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
        </ds:Transforms>
        <ds:DigestMethod 
                  Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
        <ds:DigestValue>DdQmuMjff9mkiNwmwwkex0LPHN8=</ds:DigestValue>
      </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue>DgTO6puBouHUxNWANLvNBM5XluU0Hx5xJP/E/16LC3QUv+2
yersdqQ==</ds:SignatureValue>
    <ds:KeyInfo>
      <ds:X509Data>
        <ds:X509Certificate>
MIIC6TCCAqYCBEYBMSYwCwYHKoZIzjgEAwUAMFoxDDAKBgNVBAYTA2FkZjENMAsGA1UECBMEYXNk
ZjEOMAwGA1UEBxMFYXNkZmQxDTALBgNVBAoTBGFzZGYxDTALBgNVBAsTBGFzZGYxDTALBgNVBAMT
BGFzZGYwHhcNMDcwMzIxMTMyMDM4WhcNMDcwNjE5MTMyMDM4WjBaMQwwCgYDVQQGEwNhZGYxDTAL
BgNVBAgTBGFzZGYxDjAMBgNVBAcTBWFzZGZkMQ0wCwYDVQQKEwRhc2RmMQ0wCwYDVQQLEwRhc2Rm
MQ0wCwYDVQQDEwRhc2RmMIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2
EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7
ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUA
l2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdR
WVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx
+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGALjc0JL8e3o3OVewD
06EuudHR36srFq1cVVKV3gqZHluPjzw1LfJYo1vIFMr91oYMNSnlQz5HJRuC9Av8jpeYZGoxm/Vc
5XHrICkGUFUfostU2ufGvc3k6z+pPGCSnyb2BhRnSZid1yl/MDnp5KQukXms/IGkpYqbrZcRtTs/
s9UwCwYHKoZIzjgEAwUAAzAAMC0CFAj/LVbvicwcO168koFUSMWy/phjAhUAhYK5RadC0Cebmu+3
wQbzPvQWZDA=
        </ds:X509Certificate>
      </ds:X509Data>
    </ds:KeyInfo>
  </ds:Signature>
</entry>

Notice that unlike in the encryption example, the original entry information is still present; the signature has just been added to it. The signature consists of information on how the information was processed so someone trying to verify the signature can duplicate the steps exactly in order to get the same result. If the verification process does not provide the same result, then the message is either forged or has been tempered with en route.

Once again, you can add these signed entries to a feed (see Listing 11).


Listing 11. Creating a feed of signed entries
                
...
    entry = signature.sign(entry, options);
    //entry.writeTo(System.out);  

    Feed feed = factory.newFeed();
    feed.addAuthor("Nick Chase");
    feed.addEntry(entry);

    feed.writeTo(System.out); 

  }

}

Of course, signatures are no use if you can't verify them.


Verifying a signature

Verifying a signature can be a complicated task; thankfully Abdera handles it easily (see Listing 12).


Listing 12. Verifying a signature
                
...
    feed.addEntry(entry);

    Entry entryToCheck = feed.getEntries().get(0);

    if (signature.verify(entryToCheck, null)){
    	System.out.print("The entry is valid.");
    } else {
    	System.out.print("The entry has been tampered with!");
    }
...

Here you simply check the entry as an object, but what about after you send it off as an actual feed? Listing 13 shows how to check the actual feed.


Listing 13. Checking the actual feed
                
...
        System.out.print("The entry has been tampered with!");
    }

    ByteArrayOutputStream feedOutput = new ByteArrayOutputStream();
    feed.writeTo(feedOutput);
 
    ByteArrayInputStream feedInput = 
    	          new ByteArrayInputStream(feedOutput.toByteArray());
    Document<Feed> newFeedDoc = abdera.getParser().parse(feedInput);
    Feed newFeed = newFeedDoc.getRoot();
    Entry entryToCheckFromFeed = newFeed.getEntries().get(0);

    if (signature.verify(entryToCheckFromFeed, null)){
    	System.out.println("The output entry is valid.");
    } else {
    	System.out.println("The output entry has been tampered with!");
    }
  }

}

If you run this example, you'll see that the feed and the entry are indeed valid.

Note that digital signatures verify whether the signed material has changed at all. That means a single added or removed space will invalidate the signature. For this reason, is usually not practical to sign an entire feed, because entries are typically taken out of context and used in other applications.

Summary

In this article, you saw fairly simple examples of using Atom data with both digital signatures, which verify both the sender and the integrity of the information, and encryption, which prevents unauthorized parties from obtaining sensitive information. To accomplish these tasks, you used the Apache Abdera project, which enables you to easily manipulate Atom data. Abdera also includes objects that make it possible to integrate easily with client side certificates, to automatically encrypt Atom data at the servlet level, and more. For further information, see the link to James Snell's information in the Resources.



Download

DescriptionNameSizeDownload method
Sample codex-atomencryption-source.zip7KB HTTP

Information about download methods


Resources

Learn

Get products and technologies

  • The Blogapps server: Download the server in this collection of useful RSS and Atom utilities and examples.

  • Apache Abdera package: Download and use this tool for the Atom Publishing Protocol.

Discuss

About the author

Nicholas Chase has been involved in Web site development for companies such as Lucent Technologies, Sun Microsystems, Oracle, and the Tampa Bay Buccaneers. Nick has been a high school physics teacher, a low-level radioactive waste facility manager, an online science fiction magazine editor, a multimedia engineer, an Oracle instructor, and the Chief Technology Officer of an interactive communications company. He is the author of several books, including XML Primer Plus (Sams).

Comments



Trademarks

static.content.url=/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Java technology
ArticleID=223510
ArticleTitle=Signing, encrypting, and decrypting Atom
publish-date=05222007
author1-email=ibmquestions@nicholaschase.com
author1-email-cc=dwxed@us.ibm.com