<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" 
      xmlns:thr="http://purl.org/syndication/thread/1.0">
  <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/05/introducing-nitro-lm-lite.html" />
  <link rel="self" type="application/atom+xml" href="http://www.insideria.com/atom.xml" />
  <id>tag:www.insideria.com,2009://34/tag:www.insideria.com,2009://34.36312-</id>
  <updated>2009-11-16T14:59:47Z</updated>
  <title>Comments for Introducing Nitro-LM &quot;Lite&quot; (http://www.insideria.com/2009/05/introducing-nitro-lm-lite.html)</title>
  <generator uri="http://www.sixapart.com/movabletype/">Movable Type 4.21-en</generator>
  <entry>
    <id>tag:www.insideria.com,2009://34.36312</id>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/05/introducing-nitro-lm-lite.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://blogs.oreilly.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=34/entry_id=36312" title="Introducing Nitro-LM &quot;Lite&quot;" />
    <published>2009-05-23T15:00:00Z</published>
    <updated>2009-06-08T15:26:17Z</updated>
    <title>Introducing Nitro-LM &quot;Lite&quot;</title>
    <summary><![CDATA[ &nbsp; &nbsp; &nbsp; &nbsp; I've been consulting for Simplified Logic the creators of Nitro-LM full time for the past two years. Nitro-LM is a licensing and encryption solution for software written in C/C++, Java, Eclipse, Eclipse Plugins, and Adobe...]]></summary>
    <author>
      <name>Andrew Westberg</name>
      <uri>http://www.flexjunk.com</uri>
    </author>
    
    <category term="Blogs" />
    
    <content type="html" xml:lang="en" xml:base="http://www.insideria.com/">
      <![CDATA[<img alt="nitrolm_lite.png" src="http://www.insideria.com/2009/05/22/nitrolm/nitrolm_lite.png" width="491" height="85" class="mt-image-left"/>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>I've been consulting for <a href="http://www.simplifiedlogic.com">Simplified Logic</a> the creators of <a href="http://www.nitrolm.com">Nitro-LM</a> full time for the past two years.  Nitro-LM is a licensing and encryption solution for software written in C/C++, Java, Eclipse, Eclipse Plugins, and Adobe Flex and AIR.  It differs from other software protection mechanisms out there in that it allows you to maintain control of your software from the Nitro-LM hosted cloud service while still allowing you to custom tailor the user's licensing and registration experience.  This allows for a much less draconian approach to software licensing and protection than you're probably experienced in the past.</p>

<p>During this time, I've also given numerous demos and sat in on sales calls that go something like this...</p>

<blockquote>"Wow, I didn't realize your product did all this stuff.  I'll definitely look into it in the future.  Right now though, I've already implemented a username/password system.  I was just looking for a way to encrypt and protect my Flex/AIR app from being decompiled.  Does Nitro-LM have an option for just doing encryption only?</blockquote>

<p>Nitro-LM "Lite" was announced at <a href="http://www.360flex.com">360|Flex Indy</a> to fill this obvious gap in the product line as well as meet customer demand for a solution to the problem of Flex and AIR decompiling.  Since I'm a developer myself, I thought the best way to introduce this product to other developers would be a walk-thru of encrypting an example application of an online store.  The example I'll encrypt is the standard Flex Store app used to teach the <a href="http://opensource.adobe.com/wiki/display/cairngorm/">Cairngorm</a> micro-architecture.  The Nitro-LM SWC itself is just an ActionScript API and can easily be wrapped or bundled into any of the various micro-architectures.</p>

<p>First, let's take a look at the unencrypted store app.</p>

<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><a href="http://www.insideria.com/assets_c/2009/05/flex_store.html" onclick="window.open('http://www.insideria.com/assets_c/2009/05/flex_store.html','popup','width=1053,height=645,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="http://www.insideria.com/assets_c/2009/05/flex_store-thumb-400x245.png" width="400" height="245" alt="flex_store.png" class="mt-image-none" style="" /></a></span>

<p><a href="http://flexjunk.com/examples/flexstore/flexstore.html">Direct Link</a></p>

<p>Nitro-LM "Lite" doesn't specify what you're allowed to encrypt.  You can encrypt images, small videos, Flex Applications, Flash swfs, or Modules.  In this example, we're going to convert the entire application into a single Flex Module and embed it inside a Flex Application wrapper that'll handle the Nitro-LM communication and decryption.  In a production application, I recommend that you break your application into many modules and make them as small as possible.  While Nitro-LM "Lite" performance is unnoticeable in most instances, an end-user trying to decrypt a 400kb object in memory in the flash player player might see some delay.  I try to keep the objects/modules I decrypt under 150kb or less.  This example is a bit on the heavy side since I'm decrypting an entire large module instead of breaking it down into smaller chunks.</p>

<p>First, let's take a look at the modifications I made to the main flexstore.mxml file.</p>

<p>Original:</p>
<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;"> 
<code language="perl">
<pre> 

&lt;!--
<span class="linecomment">////////////////////////////////////////////////////////////////////////////////</span>
<span class="linecomment">//</span>
<span class="linecomment">// Copyright (C) 2003-2006 Adobe Macromedia Software LLC and its licensors.</span>
<span class="linecomment">// All Rights Reserved.</span>
<span class="linecomment">// The following is Sample Code and is subject to all restrictions on such code</span>
<span class="linecomment">// as contained in the End User License Agreement accompanying this product.</span>
<span class="linecomment">// If you have received this file from a source other than Adobe,</span>
<span class="linecomment">// then your use, modification, or distribution of it requires</span>
<span class="linecomment">// the prior written permission of Adobe.</span>
<span class="linecomment">//</span>
<span class="linecomment">////////////////////////////////////////////////////////////////////////////////</span>
--&gt;
&lt;mx:<span class="category2">Application</span> pageTitle="<span class="quote">FlexStore</span>"
				layout="<span class="quote">absolute</span>" 
				minWidth="<span class="quote">990</span>" minHeight="<span class="quote">550</span>"
			    preinitialize="<span class="quote">onLoadTheme()</span>"
			    creationComplete="<span class="quote">onLoadCatalog()</span>"
			    xmlns:screens="<span class="quote">com.flexstore.view.screens.*</span>"
			    xmlns:mx="<span class="quote">http://www.adobe.com/2006/mxml</span>"&gt;
...
&lt;/mx:<span class="category2">Application</span>&gt;</pre>
</code>
 
</div></div> 

<p>Modified:</p>
<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;"> 
<code language="perl">
<pre> 

&lt;!--
<span class="linecomment">////////////////////////////////////////////////////////////////////////////////</span>
<span class="linecomment">//</span>
<span class="linecomment">// Copyright (C) 2003-2006 Adobe Macromedia Software LLC and its licensors.</span>
<span class="linecomment">// All Rights Reserved.</span>
<span class="linecomment">// The following is Sample Code and is subject to all restrictions on such code</span>
<span class="linecomment">// as contained in the End User License Agreement accompanying this product.</span>
<span class="linecomment">// If you have received this file from a source other than Adobe,</span>
<span class="linecomment">// then your use, modification, or distribution of it requires</span>
<span class="linecomment">// the prior written permission of Adobe.</span>
<span class="linecomment">//</span>
<span class="linecomment">////////////////////////////////////////////////////////////////////////////////</span>
--&gt;
&lt;mx:Module pageTitle="<span class="quote">FlexStore</span>"
				layout="<span class="quote">absolute</span>" 
				<span class="category2">width</span>="<span class="quote">100%</span>"
				minWidth="<span class="quote">990</span>" minHeight="<span class="quote">550</span>"
			    preinitialize="<span class="quote">onLoadTheme()</span>"
			    creationComplete="<span class="quote">onLoadCatalog()</span>"
			    xmlns:screens="<span class="quote">com.flexstore.view.screens.*</span>"
			    xmlns:mx="<span class="quote">http://www.adobe.com/2006/mxml</span>"&gt;
...
&lt;/mx:Module&gt;</pre>
</code>
 
</div></div> 

<p>I've converted the main Application into an mx:Module and modified the width property.  In the project properties inside FlexBuilder, I've made the modifications to compile flexstore.mxml as a module and created a new Application called EncryptedFlexStore.mxml.  This EncryptedFlexStore application will be my container for the newly encrypted flexstore module.  Let's take a look inside:</p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;"> 
<code language="perl">
<pre> 

&lt;?xml <span class="category2">version</span>="<span class="quote">1.0</span>" encoding="<span class="quote">utf-8</span>"?&gt;
&lt;mx:<span class="category2">Application</span> xmlns:mx="<span class="quote">http://www.adobe.com/2006/mxml</span>" layout="<span class="quote">absolute</span>" creationComplete="<span class="quote">init()</span>"&gt;
	&lt;mx:Script&gt;
		&lt;![CDATA[
		<span class="category1">import</span> com.hurlant.crypto.rsa.RSAKey;
		<span class="category1">import</span> com.nitrolm.ILicenseClient;
		<span class="category1">import</span> com.nitrolm.LicenseClientEvent;
		<span class="category1">import</span> com.nitrolm.LicenseClientFactory;
		<span class="category1">import</span> com.nitrolm.NLMConstants;
		<span class="category1">import</span> com.nitrolm.ProductKeys;
		
		<span class="category1">import</span> de.polygonal.ds.HashMap;
		
		<span class="category1">import</span> flash.events.Event;
		<span class="category1">import</span> flash.system.ApplicationDomain;
		<span class="category1">import</span> flash.utils.ByteArray;
		
		<span class="category1">import</span> mx.controls.Alert;
		<span class="category1">import</span> mx.modules.ModuleLoader;
		
		<span class="linecomment">//the embedded product key (allows for secure communication to Nitro-LM)</span>
		[Embed (source="<span class="quote">rQHrpVZjnlpstlfGQ1Pv.ser</span>", mimeType="<span class="quote">application/octet-stream</span>")]
		<span class="category1">private</span> <span class="category1">var</span> ServerCommunicationKey:Class;
		
		<span class="linecomment">//the encrypted version of the Flickr Book SWF</span>
		<span class="linecomment">//this will be copied into the source folder by the ANT script</span>
		[Embed (source="<span class="quote">flexstore_e.swf</span>", mimeType="<span class="quote">application/octet-stream</span>")]
		<span class="category1">private</span> <span class="category1">var</span> EncryptedSWF:Class;
		
		
		<span class="linecomment">//the product we created in the Nitro-LM administration tool</span>
		<span class="category1">private</span> <span class="category1">static</span> const CAIRNGORM_STORE_PRODUCT:<span class="category2">String</span> = "<span class="quote">rQHrpVZjnlpstlfGQ1Pv</span>";
		<span class="category1">private</span> <span class="category1">static</span> const CAIRNGORM_STORE_VERSION:<span class="category2">String</span> = "<span class="quote">1</span>";
		
		<span class="linecomment">//the factory that generates an ILicenseClient interface capable of communicating with Nitro-LM</span>
		<span class="category1">private</span> <span class="category1">var</span> factory:LicenseClientFactory = <span class="category1">null</span>;
		
		<span class="linecomment">//the main interface we'll use for communicating with Nitro-LM</span>
		<span class="category1">private</span> <span class="category1">var</span> licenseClient:ILicenseClient = <span class="category1">null</span>;
		
		<span class="category1">private</span> <span class="category1">function</span> <span class="category2">init</span>():<span class="category1">void</span>
		{
 			<span class="linecomment">//create an instance of our server communication key so that the Nitro-LM library</span>
 			<span class="linecomment">//will use it when communicating to the server in a secure fashion.</span>
 			ProductKeys.putPublicKey(CAIRNGORM_STORE_PRODUCT, <span class="category1">new</span> ServerCommunicationKey());
 			
 			<span class="linecomment">//initialize the factory and call initNitroLMDone with Event.COMPLETE</span>
 			<span class="linecomment">//we have to make sure we can communicate with the servers and everything is initialized</span>
 			<span class="linecomment">//before making any Nitro-LM API calls</span>
 			factory = <span class="category1">new</span> LicenseClientFactory(initNitroLMDone);
 		}
		
		<span class="category1">private</span> <span class="category1">function</span> initNitroLMDone(event:Event):<span class="category1">void</span>
		{
 			<span class="linecomment">//get an ILicenseClient interface</span>
 			licenseClient = factory.getInstance();
 			
 			<span class="linecomment">//request a decryption key for the Cairngorm Store product</span>
 			licenseClient.addEventListener(LicenseClientEvent.LICENSE_RESPONSE, handleRequestKeyResponse);
 			licenseClient.requestKey(CAIRNGORM_STORE_PRODUCT, CAIRNGORM_STORE_VERSION);
 		}
		
		<span class="category1">private</span> <span class="category1">function</span> handleRequestKeyResponse(event:LicenseClientEvent):<span class="category1">void</span>
		{
 			<span class="linecomment">//remove the event listener to clean up memory</span>
 			licenseClient.removeEventListener(LicenseClientEvent.LICENSE_RESPONSE, handleRequestKeyResponse);
 			
 			<span class="linecomment">//make sure we got a valid response code from Nitro-LM for our key request</span>
 			<span class="category1">if</span>(event.response == NLMConstants.RESPONSE_OK)
 			{
  				<span class="category1">if</span>(event.<span class="category2">data</span> != <span class="category1">null</span>)
  				{
   					<span class="category1">var</span> keyBytes:ByteArray = (event.<span class="category2">data</span> as HashMap).find("<span class="quote">key</span>");
   					<span class="category1">if</span>(keyBytes != <span class="category1">null</span>)
   					{
    						<span class="category1">var</span> decryptKey:RSAKey = ProductKeys.readRSAPublicKey(keyBytes);
    						<span class="category1">var</span> decryptedSWF:ByteArray = licenseClient.decryptModule(<span class="category1">new</span> EncryptedSWF(), decryptKey);
    						
    						<span class="category1">var</span> loader:ModuleLoader = <span class="category1">new</span> ModuleLoader();
    						loader.applicationDomain = ApplicationDomain.currentDomain;
    						loader.percentWidth = 100;
    						loader.percentHeight = 100;
    						loader.loadModule("<span class="quote">flexstore.swf</span>", decryptedSWF);
    						<span class="category1">this</span>.addChild(loader);
    						<span class="category1">return</span>;
    					}
   				}
  			}
 			Alert.<span class="category2">show</span>(NLMConstants.responseToString(event.response));
 		}
		]]&gt;
	&lt;/mx:Script&gt;
&lt;/mx:<span class="category2">Application</span>&gt;</pre>
</code>
 
</div></div> 

<p>In Nitro-LM "Lite", there are actually 4 keys (2 keypairs) in play.  At the highest level, Nitro-LM uses RSA Public/Private keypairs for both communicating to the Nitro-LM cloud and encrypting assets. </p>
<p>The first keypair is the communication keypair.  When you register for Nitro-LM "Lite", you download the public key (*.ser) file for your particular application.  The private counterpart to this is never stored anywhere except on the cloud servers so that Nitro-LM can understand the requests you're sending it.</p>
<p>The second keypair is the encryption keypair.  You also download the private encryption key (*.vser) file when you register for Nitro-LM "Lite".  This file is used ONLY during the build process and should never get out into the clear.</p>
<p>The process an application goes through to decrypt an asset in memory is as follows.
<ol>
<li>Use the public communication key to encrypt and send a request to the cloud for a decryption key.  Note that ONLY the server can decrypt and understand this request.</li>
<li>Receive and unpackage the decryption key from the server and use it to decrypt some type of asset.  In our example, we're decrypting a Flex Module.</li>
</ol>
</p>

<p>There are many additional layers of security and encryption built into Nitro-LM, but for the sake of a public article, we're only going to be discussing the outermost RSA layer that the developer will interact with.</p>

<p>If you've been able to follow the code thus far, you should have a fairly good idea of how all the decryption is working.  But how do you actually encrypt and package the module SWF in the first place?  The answer to this is in an <a href="http://ant.apache.org/">ANT</a> script that is used to compile the application.  I use the standard flexTasks that ship with the Flex SDK for compiling the SWF and module files.  I then also use a special nitrolm-encrypt task that ships as a JAR file along with Nitro-LM "Lite".</p>

<p>In my example, I use a 4-phase build process.  I first build the wrapper to generate a link report.  Second, I compile the module SWF using that link report to make it as small as possible.  Third, I encrypt the module SWF using the keys I've downloaded.  Finally, I re-build the wrapper since I'm embedding the encrypted swf inside the app.  This isn't absolutely necessary as you could also get the encrypted swf bytes through a URL connection or locally in an AIR app if you wanted to.  It just made for a nice clean example for my demo.</p>

<div class="acode" style="overflow: auto; padding: 10px;" ><div style="overflow-x: visible;"> 
<code language="perl">
<pre> 

&lt;?xml <span class="category2">version</span>="<span class="quote">1.0</span>" encoding="<span class="quote">ISO-8859-1</span>"?&gt;
&lt;project <span class="category2">name</span>="<span class="quote">NitroEncryptedModulesDemo</span>"  basedir="<span class="quote">.</span>" <span class="category1">default</span>="<span class="quote">compile.release</span>"&gt;

	&lt;property <span class="category2">name</span>="<span class="quote">OPTIMIZE</span>" value="<span class="quote">true</span>"/&gt;
	&lt;property <span class="category2">name</span>="<span class="quote">DEBUG</span>" value="<span class="quote">false</span>"/&gt;
	
    &lt;property <span class="category2">name</span>="<span class="quote">FLEX_HOME</span>" value="<span class="quote">C:/Program Files/Adobe/Flex Builder 3 Plug-in/sdks/3.3.0</span>"/&gt;
	
	&lt;property <span class="category2">name</span>="<span class="quote">src.dir</span>" value="<span class="quote">.</span>"/&gt;
	&lt;property <span class="category2">name</span>="<span class="quote">lib.dir</span>" value="<span class="quote">../libs</span>"/&gt;
    &lt;property <span class="category2">name</span>="<span class="quote">out.dir</span>" value="<span class="quote">C:/Program Files/Apache Software Foundation/Apache2.2/htdocs/encryptedflexstore</span>"/&gt;
    &lt;property <span class="category2">name</span>="<span class="quote">jars.dir</span>" value="<span class="quote">../jars</span>"/&gt;
    	
	&lt;taskdef <span class="category2">name</span>="<span class="quote">nitrolm-encrypt</span>" classname="<span class="quote">com.simplifiedlogic.nitrolm.LMEncryptAsset</span>" classpath="<span class="quote">${jars.dir}/AssetEncrypterX.jar</span>"/&gt;
	&lt;taskdef resource="<span class="quote">flexTasks.tasks</span>" classpath="<span class="quote">${FLEX_HOME}/ant/lib/flexTasks.jar</span>"/&gt;
		
	&lt;<span class="category2">target</span> <span class="category2">name</span>="<span class="quote">clean</span>" description="<span class="quote">Clean the project</span>"&gt;
		&lt;<span class="category1">delete</span> dir="<span class="quote">${out.dir}</span>" failonerror="<span class="quote">false</span>"/&gt;
	&lt;/<span class="category2">target</span>&gt;
			
	&lt;<span class="category2">target</span> <span class="category2">name</span>="<span class="quote">init</span>" description="<span class="quote">initialize the project</span>" depends="<span class="quote">clean</span>"&gt;
		&lt;mkdir dir="<span class="quote">${out.dir}</span>"/&gt;
		&lt;<span class="category2">copy</span> todir="<span class="quote">${out.dir}</span>" includeemptydirs="<span class="quote">false</span>"&gt;
			&lt;fileset dir="<span class="quote">${src.dir}</span>"&gt;
				&lt;exclude <span class="category2">name</span>="<span class="quote">**/*.as</span>"/&gt;
				&lt;exclude <span class="category2">name</span>="<span class="quote">**/*.mxml</span>"/&gt;
				&lt;exclude <span class="category2">name</span>="<span class="quote">**/build.xml</span>"/&gt;
				&lt;exclude <span class="category2">name</span>="<span class="quote">**/*.properties</span>"/&gt;
				&lt;exclude <span class="category2">name</span>="<span class="quote">**/*.ser</span>"/&gt;
				&lt;exclude <span class="category2">name</span>="<span class="quote">**/*.vser</span>"/&gt;
				&lt;include <span class="category2">name</span>="<span class="quote">**/*</span>"/&gt;
			&lt;/fileset&gt;
		&lt;/<span class="category2">copy</span>&gt;
	&lt;/<span class="category2">target</span>&gt;
	
	&lt;<span class="category2">target</span> <span class="category2">name</span>="<span class="quote">compile.release</span>" description="<span class="quote">Compile wrapper swf pass 1,2,3</span>" depends="<span class="quote">init</span>"&gt;
		&lt;!-- compile loader SWF pass 1 so we have a link report --&gt;
		&lt;mxmlc file="<span class="quote">EncryptedFlexStore.mxml</span>" output="<span class="quote">${out.dir}/EncryptedFlexStore.swf</span>"
			debug="<span class="quote">${DEBUG}</span>"
			optimize="<span class="quote">${OPTIMIZE}</span>"
			link-report="<span class="quote">${out.dir}/report.xml</span>"
			locale="<span class="quote">en_US</span>"&gt;

			&lt;compiler.context-root&gt;/EncryptedFlexStore&lt;/compiler.context-root&gt;
			&lt;source-path path-element="<span class="quote">${src.dir}</span>"/&gt;
			&lt;library-path dir="<span class="quote">${FLEX_HOME}/frameworks/libs</span>" append="<span class="quote">true</span>"&gt;
				&lt;include <span class="category2">name</span>="<span class="quote">*.swc</span>"/&gt;
			&lt;/library-path&gt;
			&lt;library-path dir="<span class="quote">${FLEX_HOME}/frameworks/locale</span>" append="<span class="quote">true</span>"&gt;
				&lt;include <span class="category2">name</span>="<span class="quote">{locale}</span>"/&gt;
			&lt;/library-path&gt;			
			&lt;library-path dir="<span class="quote">${lib.dir}</span>" append="<span class="quote">true</span>"&gt;
				&lt;include <span class="category2">name</span>="<span class="quote">FlexNitroLMLiteInterface.swc</span>"/&gt;
			&lt;/library-path&gt;			
		&lt;/mxmlc&gt;
				
		&lt;!-- compile module SWF to protect including link report.xml --&gt;
		&lt;mxmlc
			file="<span class="quote">${src.dir}/flexstore.mxml</span>"
			output="<span class="quote">${src.dir}/flexstore_e.swf</span>"
			debug="<span class="quote">${DEBUG}</span>"
			optimize="<span class="quote">${OPTIMIZE}</span>"
			<span class="category2">load</span>-externs="<span class="quote">${out.dir}/report.xml</span>"
			locale="<span class="quote">en_US</span>"&gt;

			&lt;compiler.context-root&gt;/FlexStore&lt;/compiler.context-root&gt;
			&lt;source-path path-element="<span class="quote">${src.dir}</span>"/&gt;
			&lt;library-path dir="<span class="quote">${FLEX_HOME}/frameworks/libs</span>" append="<span class="quote">true</span>"&gt;
				&lt;include <span class="category2">name</span>="<span class="quote">*.swc</span>"/&gt;
			&lt;/library-path&gt;
			&lt;library-path dir="<span class="quote">${FLEX_HOME}/frameworks/locale</span>" append="<span class="quote">true</span>"&gt;
				&lt;include <span class="category2">name</span>="<span class="quote">{locale}</span>"/&gt;
			&lt;/library-path&gt;			
			&lt;library-path dir="<span class="quote">${lib.dir}</span>" append="<span class="quote">true</span>"&gt;
				&lt;include <span class="category2">name</span>="<span class="quote">*.swc</span>"/&gt;
			&lt;/library-path&gt;			
		&lt;/mxmlc&gt;
		
		&lt;!-- <span class="category1">delete</span> the link report --&gt;
		&lt;<span class="category1">delete</span> file="<span class="quote">${out.dir}/report.xml</span>" /&gt;
		
		&lt;!-- encrypt the swf to protect --&gt;
		&lt;nitrolm-encrypt
			filename="<span class="quote">${src.dir}/flexstore_e.swf</span>"
			product="<span class="quote">rQHrpVZjnlpstlfGQ1Pv</span>"
			library="<span class="quote">rQHrpVZjnlpstlfGQ1Pv</span>"
			keydir="<span class="quote">.</span>"/&gt;

		&lt;!-- re-compile pass 2 of the loader SWF so the <span class="category1">new</span> encrypted protected swf is embedded correctly --&gt;
		&lt;mxmlc file="<span class="quote">EncryptedFlexStore.mxml</span>" output="<span class="quote">${out.dir}/EncryptedFlexStore.swf</span>"
			debug="<span class="quote">${DEBUG}</span>"
			optimize="<span class="quote">${OPTIMIZE}</span>"
			locale="<span class="quote">en_US</span>"&gt;

			&lt;compiler.context-root&gt;/EncryptedFlexStore&lt;/compiler.context-root&gt;
			&lt;source-path path-element="<span class="quote">${src.dir}</span>"/&gt;
			&lt;library-path dir="<span class="quote">${FLEX_HOME}/frameworks/libs</span>" append="<span class="quote">true</span>"&gt;
				&lt;include <span class="category2">name</span>="<span class="quote">*.swc</span>"/&gt;
			&lt;/library-path&gt;
			&lt;library-path dir="<span class="quote">${FLEX_HOME}/frameworks/locale</span>" append="<span class="quote">true</span>"&gt;
				&lt;include <span class="category2">name</span>="<span class="quote">{locale}</span>"/&gt;
			&lt;/library-path&gt;			
			&lt;library-path dir="<span class="quote">${lib.dir}</span>" append="<span class="quote">true</span>"&gt;
				&lt;include <span class="category2">name</span>="<span class="quote">FlexNitroLMLiteInterface.swc</span>"/&gt;
			&lt;/library-path&gt;			
		&lt;/mxmlc&gt;
		
		&lt;<span class="category2">html</span>-wrapper 
		            title="<span class="quote">Flex Store</span>"
		            file="<span class="quote">index.html</span>"
		            <span class="category2">height</span>="<span class="quote">100%</span>"
		            <span class="category2">width</span>="<span class="quote">100%</span>"
		            bgcolor="<span class="quote">grey</span>"
		            application="<span class="quote">app</span>"
		            swf="<span class="quote">EncryptedFlexStore</span>"
		            <span class="category2">version</span>-major="<span class="quote">9</span>"
		            <span class="category2">version</span>-minor="<span class="quote">0</span>"
		            <span class="category2">version</span>-revision="<span class="quote">0</span>"
		            history="<span class="quote">true</span>"
		            template="<span class="quote">express-installation</span>"
		            output="<span class="quote">${out.dir}</span>"/&gt;
	&lt;/<span class="category2">target</span>&gt;
&lt;/project&gt;</pre>
</code>
 
</div></div> 

<p>Finally, let's take a look at the results of our labor.  Everything works as it did before except that all of the code is protected from a decompiler attack.</p>

<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><a href="http://www.insideria.com/assets_c/2009/05/nitrolm_after.html" onclick="window.open('http://www.insideria.com/assets_c/2009/05/nitrolm_after.html','popup','width=1053,height=645,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="http://www.insideria.com/assets_c/2009/05/nitrolm_after-thumb-400x245.png" width="400" height="245" alt="nitrolm_after.png" class="mt-image-none" style="" /></a></span>

<p><a href="http://flexjunk.com/examples/encryptedflexstore/index.html">Direct Link</a></p>

<p>So, now that you've been introduced to Nitro-LM "Lite", the next step in the learning process is to browse through the <a href="http://www.nitrolm.com">Nitro-LM</a> website, and also the <a href="https://license.nitromation.com/NitroAdminLite/index.html?id=693">Nitro-LM "Lite" administration app</a>.

<p>After registering for the Nitro-LM "Lite" Admin tool, you'll get access to the example code I've used for this article.  It doesn't cost anything to register, or to use the example keys included in the example downloads against your own applications.  I'd recommend against using the example keys in a production app because they're publicly available and they get rotated every so often.  At $500/product/year, Purchasing keys for Nitro-LM "Lite" is priced similarly to buying an SSL certificate for a website.</p>

<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><a href="http://www.insideria.com/assets_c/2009/05/nitrolm_support.html" onclick="window.open('http://www.insideria.com/assets_c/2009/05/nitrolm_support.html','popup','width=986,height=731,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="http://www.insideria.com/assets_c/2009/05/nitrolm_support-thumb-400x296.png" width="400" height="296" alt="nitrolm_support.png" class="mt-image-none" style="" /></a></span>]]>
      
    </content>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36312-comment:2060401</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36312" type="text/html" href="http://www.insideria.com/2009/05/introducing-nitro-lm-lite.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/05/introducing-nitro-lm-lite.html#comment-2060401" />
    <title>Comment from Samuel Moshe on 2009-05-26</title>
    <author>
        <name>Samuel Moshe</name>
        <uri></uri>
    </author>
    <content type="html" xml:lang="en" xml:base="">
        <![CDATA[<p>Focusing on source code as equity is a mistake.<br />
Companies that do this are wasting money and time. Source code is not an asset, and is basically meaningless. In application space, your biggest and only asset is solving a problem worth solving in a way that makes sense for your users to do it. It's the only thing that you will ever have. Even if someone did steal your source code, there's no telling they would be able to do anything with it.</p>

<p>In general though, it's not that hard to steal anything, especially process, which you should be much more concerned about than code. Maybe, the better idea would be to focus on developing something worth using.</p>

<p>Just my two cents.</p>]]>
    </content>
    <published>2009-05-26T14:17:24Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36312-comment:2060409</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36312" type="text/html" href="http://www.insideria.com/2009/05/introducing-nitro-lm-lite.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/05/introducing-nitro-lm-lite.html#comment-2060409" />
    <title>Comment from Andrew Westberg on 2009-05-26</title>
    <author>
        <name>Andrew Westberg</name>
        <uri>http://www.nitrolm.com/blog</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.nitrolm.com/blog">
        <![CDATA[<p>@Samuel,</p>

<p>You're correct.  Your thoughts that source code itself is not an asset are dead on.  The techniques, processes, and informational data it may contain, however are important to protect.  For example, someone with a financial flex app may not have any real data or IP inside the app itself, but decompiling and studying the app 's operation could have lots of useful information for a hacker trying to learn how to go after the server data directly.</p>]]>
    </content>
    <published>2009-05-26T15:10:55Z</published>
  </entry>

  <entry>
    <id>tag:www.insideria.com,2009://34.36312-comment:2066986</id>
    <thr:in-reply-to ref="tag:www.insideria.com,2009://34.36312" type="text/html" href="http://www.insideria.com/2009/05/introducing-nitro-lm-lite.html"/>
    <link rel="alternate" type="text/html" href="http://www.insideria.com/2009/05/introducing-nitro-lm-lite.html#comment-2066986" />
    <title>Comment from Andrew Westberg on 2009-06-23</title>
    <author>
        <name>Andrew Westberg</name>
        <uri>http://www.nitrolm.com/blog</uri>
    </author>
    <content type="html" xml:lang="en" xml:base="http://www.nitrolm.com/blog">
        <![CDATA[<p>I've created a separate blog post that should explain in more detail why it's important to protect your source code.  This takes you step-by-step through cracking an AIR application.</p>

<p><a href='http://www.nitrolm.com/blog/2009/06/23/how-to-hack-an-air-app-swf/'>How to Hack an AIR app SWF</a></p>]]>
    </content>
    <published>2009-06-23T19:06:58Z</published>
  </entry>

</feed
