You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@santuario.apache.org by bl...@apache.org on 2004/02/03 12:06:07 UTC

cvs commit: xml-security/doc/site/src/documentation/content/xdocs/c programming.xml

blautenb    2004/02/03 03:06:07

  Modified:    doc/site/src/documentation/content/xdocs/c programming.xml
  Log:
  Encrypt programming HOWTO
  
  Revision  Changes    Path
  1.3       +238 -0    xml-security/doc/site/src/documentation/content/xdocs/c/programming.xml
  
  Index: programming.xml
  ===================================================================
  RCS file: /home/cvs/xml-security/doc/site/src/documentation/content/xdocs/c/programming.xml,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- programming.xml	9 Aug 2003 12:02:33 -0000	1.2
  +++ programming.xml	3 Feb 2004 11:06:07 -0000	1.3
  @@ -478,5 +478,243 @@
   		  ]]></source>
   	  </section>
   	</section>
  +	<section id="simpleencrypt">
  +	  <title>A simple encryption example</title>
  +	  <p>
  +		The next example encrypts an element (and all its children) from
  +		a pre-generated document.  It uses a randomly generated key to
  +		handle the bulk encryption, and then encrypts this using an RSA
  +		public key.  The resultant encrypted key is embedded in an
  +		&lt;EncryptedKey&gt; element.
  +	  </p>
  +	  <p>
  +		This example can be found in the src/samples directory as
  +		<em>simpleEncrypt.cpp</em>.
  +	  </p>
  +	  <section>
  +		<title>Setup</title>
  +		<p>
  +		  The first step is initialisation of Xerces, Xalan (if used) and
  +		  XML-Security.  Once this is done, we create a document.  For 
  +		  brevity, the details of the call to <em>createLetter</em> are
  +		  not included on this page.  The function is very simple - it creates
  +		  an XML DOM document that represents a letter, and sets a global
  +		  variable (<em>g_toEncrypt</em>) that will be used later on to
  +		  determine what node to encrypt.
  +		</p>
  +		<source><![CDATA[
  +int main (int argc, char **argv) {
  +
  +    try {
  +        XMLPlatformUtils::Initialize();
  +#ifndef XSEC_NO_XALAN
  +        XalanTransformer::initialize();
  +#endif
  +        XSECPlatformUtils::Initialise();
  +    }
  +    catch (const XMLException &e) {
  +
  +        cerr << "Error during initialisation of Xerces" << endl;
  +        cerr << "Error Message = : "
  +             << e.getMessage() << endl;
  +
  +    }
  +
  +    // Create a blank Document
  +
  +    DOMImplementation *impl = 
  +        DOMImplementationRegistry::getDOMImplementation(MAKE_UNICODE_STRING("Core"));
  +	
  +    // Create a letter
  +    DOMDocument *doc = createLetter(impl);
  +		  ]]></source>
  +	  </section>
  +	  <section>
  +		<title>Setup for Encryption</title>
  +		<p>
  +		  Once the library is initialised, we create a <em>XENCCipher</em>
  +		  object in a manner similar to the creation of a 
  +		  <em>DSIGSignature</em> object.  The <em>XENCCipher</em> object
  +		  is used to actually perform encryption/decryption functions and
  +		  to manipulate the various encryption objects provided by the
  +		  library.
  +		</p>
  +		<p>
  +		  As well as creating the <em>XENCCipher</em> object, the sample
  +		  uses the <em>RAND_bytes</em> function within the 
  +		  <strong>OpenSSL</strong>
  +		  library to create a random key that will be used during the
  +		  encryption process.
  +		</p>
  +		<source><![CDATA[
  +    try {
  +		
  +        /* Create the cipher object that we need */
  +
  +        XSECProvider prov;
  +        XENCCipher *cipher;
  +
  +        cipher = prov.newCipher(doc);
  +
  +        /* Now generate a random key that we can use to encrypt the element
  +         *
  +         * First check the status of the random generation in OpenSSL
  +         */
  +
  +        if (RAND_status() != 1) {
  +
  +            cerr << "OpenSSL random generation not properly initialised" << endl;
  +            exit(1);
  +
  +        }
  +
  +        unsigned char keyBuf[24];
  +        if (RAND_bytes(keyBuf, 24) == 0) {
  +
  +            cerr << "Error obtaining 24 bytes of random from OpenSSL" << endl;
  +            exit(1);
  +
  +        }
  +]]></source>
  +	  </section>
  +	  <section>
  +		<title>Encryption of Element</title>
  +		<p>
  +		  The actual code to perform encryption is very small.  Most of the
  +		  complexity for standard encryption is hidden within the library.
  +		</p>
  +		<p>
  +		  The first two lines of code wrap the generated key bytes in an
  +		  OpenSSL 3DES key.  This is then passed into the <em>cipher</em>
  +		  object with a call to <em>setKey(key)</em>.
  +		</p>
  +		<p>
  +		  The last line in the following block performs the actual encryption.
  +		  the first parameter to <em>cipher->encryptElement</em> is the 
  +		  node that will be encrypted.  The second is the algorithm to be 
  +		  used.  This is used to calcualte the Algorithm URI to be set in
  +		  the &lt;EncryptedData&gt; element.
  +		</p>
  +		<p>
  +		  This call to <em>EncryptElement</em> will encrypt the provided
  +		  element using the key set previously.  The passed in element will
  +		  be replaced with an &lt;EncryptedData&gt; element containing the
  +		  encrypted version of the element and all its children.
  +		</p>
  +		<p>
  +		  If no further information is required to be embedded in the
  +		  &lt;EncryptedData&gt; structure (such as &lt;KeyInfo&gt; nodes),
  +		  the usage of the library could be terminated here.
  +		</p>
  +		<source><![CDATA[
  +        /* Wrap this in a Symmetric 3DES key */
  +
  +        OpenSSLCryptoSymmetricKey * key = 
  +            new OpenSSLCryptoSymmetricKey(XSECCryptoSymmetricKey::KEY_3DES_192);
  +        key->setKey(keyBuf, 24);
  +        cipher->setKey(key);
  +
  +        /* Encrypt the element that needs to be hidden */
  +        cipher->encryptElement(g_toEncrypt, ENCRYPT_3DES_CBC);
  +]]></source>
  +	  </section>
  +	  <section>
  +		<title>Create an &lt;EncryptedKey&gt;</title>
  +		<p>
  +		  The following snippet of code uses the previously created
  +		  <em>XENCCipher</em> object to encrypt the pseudo random key using
  +		  an RSA key loaded from a X.509 certificate.
  +		</p>
  +		<p>
  +		  The first two lines load the certificate into an OpenSSLCryptoX509
  +		  structure, which is then used to extract the public key from the
  +		  certificate and pass into the cipher.
  +		</p>
  +		<p>
  +		  A call to <em>setKEK</em> is used rather than <em>setKey</em>.
  +		  This call is used to tell the cipher object that the key being used
  +		  is a Key Encryption Key, and should be used for encrypting/decrypting
  +		  &lt;EncryptedKey&gt; elements.
  +		</p>
  +		<p>
  +		  The final line actually performs the encryption and created
  +		  the &lt;EncryptedKey&gt; structure.  The first two parameters define
  +		  the buffer and its length to be encrypted.  The last defines the
  +		  encryption algorithm to be used.
  +		</p>
  +		<p>
  +		  The <em>encryptedKey</em> method returns an <em>XENCEncryptedKey</em>
  +		  object.  This contains the DOM structure for the object, but it is
  +		  not yet rooted in a particular document.  (Although it is created
  +		  using the <em>DOMDocument</em> that was passed in during the call
  +		  to <em>newCipher</em>.)
  +		</p>
  +		<source><![CDATA[
  +        /* Now lets create an EncryptedKey element to hold the generated key */
  +
  +        /* First lets load the public key in the certificate */
  +        OpenSSLCryptoX509 * x509 = new OpenSSLCryptoX509();
  +        x509->loadX509Base64Bin(cert, strlen(cert));
  +	
  +        /* Now set the Key Encrypting Key (NOTE: Not the normal key) */
  +        cipher->setKEK(x509->clonePublicKey());
  +		
  +
  +        /* Now do the encrypt, using RSA with PKCS 1.5 padding */
  +
  +        XENCEncryptedKey * encryptedKey = 
  +            cipher->encryptKey(keyBuf, 24, ENCRYPT_RSA_15);
  +]]></source>
  +	  </section>
  +	  <section>
  +		<title>Append &lt;EncryptedKey&gt; to &lt;EncryptedData&gt;</title>
  +		<p>
  +		  The final part (other than outputting the result) is to 
  +		  retrieve the &lt;EncryptedData&gt; element that was previously 
  +		  created and append the newly created &lt;EncryptedKey&gt; as a 
  +		  &lt;KeyInfo&gt; element.
  +		</p>
  +<source><![CDATA[
  +        /*
  +         * Add the encrypted Key to the previously created EncryptedData, which
  +         * we first retrieve from the cipher object.  This will automatically create
  +         * the appropriate <KeyInfo> element within the EncryptedData
  +         */
  +
  +        XENCEncryptedData * encryptedData = cipher->getEncryptedData();
  +        encryptedData->appendEncryptedKey(encryptedKey);
  +]]></source>
  +	  </section>
  +	  <p>
  +		The above code results in a document that contains the newly created
  +		&lt;EncryptedData&gt; as follows:
  +	  </p>
  +<source><![CDATA[
  +<Letter>
  +<ToAddress>The address of the Recipient</ToAddress>
  +<FromAddress>The address of the Sender</FromAddress>
  +<xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" 
  +xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
  +<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
  +<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  +<xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
  +<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
  +<xenc:CipherData>
  +<xenc:CipherValue>Wh8pAkDsQceHiktGxnlhXGfEMPDOLB6FwWp8PLedFEB3L3F6xHUoCOerIvA7Pgvv
  +VYzVqLv4a5x5YdnCqikkFBLE/fruAUe2Z8ZTEn/CaPYmpzU6qYHALCl7Q61LcbqH
  +R87TzroBYsYwfHmXmrKHL9K9sB6zmuec1TjVzm2c/Xs=
  +</xenc:CipherValue>
  +</xenc:CipherData>
  +</xenc:EncryptedKey>
  +</ds:KeyInfo>
  +<xenc:CipherData>
  +<xenc:CipherValue>YhqQciiFkLG1z0I1TJC6Pewnzw/gmVuGqcTvHtWpgak/b3NQDRAlv07lJOmBLoHX
  +23LQ1CdPSxvnyerlJGwkY6xJ0M5tjpDregTVcECXo/bd+x8eIsF2kaawoZGCqD1K
  +96T36Fx9rHek9bY/Hp1OiQ==
  +</xenc:CipherValue>
  +</xenc:CipherData>
  +</xenc:EncryptedData></Letter>
  +]]></source>
  +	</section>
     </body>
   </document>