<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>seoxys.com&#187; Business</title>
	<atom:link href="http://www.seoxys.com/category/business/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.seoxys.com</link>
	<description></description>
	<lastBuildDate>Mon, 17 Jan 2011 00:49:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>The Azure License: meaningful attribution</title>
		<link>http://www.seoxys.com/azure-license/</link>
		<comments>http://www.seoxys.com/azure-license/#comments</comments>
		<pubDate>Tue, 27 Oct 2009 20:59:01 +0000</pubDate>
		<dc:creator>kenneth</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[Release]]></category>

		<guid isPermaLink="false">http://www.seoxys.com/?p=233</guid>
		<description><![CDATA[Open-source licensing can be a real nightmare. Some licenses are nearly impossible to decipher, while some (namely&#8201;&#8211;&#8201;the GNU GPL) are just pure&#160;evil. I have been trying to find a software license which, like the Creative Commons Attribution license, would let the licensee do pretty much anything with the software, except it would require attribution in [...]]]></description>
			<content:encoded><![CDATA[<p>Open-source licensing can be a real nightmare. Some licenses are nearly impossible to decipher, while some (namely&thinsp;&#8211;&thinsp;the GNU GPL) are just <a href="http://www.red-sweater.com/blog/825/getting-pretty-lonely">pure&nbsp;evil</a>.</p>
<p>I have been trying to find a software license which, like the Creative Commons Attribution license, would let the licensee do pretty much anything with the software, except it would require attribution in a meaningful way. That is to say, documentation and/or credits of any derivative&nbsp;work.</p>
<p>The MIT license came closest to this, and it is the base on which the Azure License was&nbsp;written.</p>
<p>A good way to give attribution, as required by the license, would be a friendly &ldquo;Contains code by Copyright Holder [linked]&rdquo; or &ldquo;Special thanks to Copyright Holder [linked]&rdquo; in the about&nbsp;box.</p>
<p>Without further ado, the Azure&nbsp;License:</p>
<blockquote><p>The Azure&nbsp;License</p>
<p>Copyright (c) {year} {copyright&nbsp;holders}</p>
<p>Attribute to {individual or group name} -&nbsp;{link}</p>
<p>You (the licensee) are hereby granted permission, free of charge, to deal in this software or source code (this &#8220;Software&#8221;) without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sublicense this Software, subject to the following&nbsp;conditions:</p>
<p>You must give attribution to the party mentioned above, by name and by hyperlink, in the about box, credits document and/or documentation of any derivative work using a substantial portion of this&nbsp;Software.</p>
<p>You may not use the name of the copyright holder(s) to endorse or promote products derived from this Software without specific prior written&nbsp;permission.</p>
<p>THIS SOFTWARE IS PROVIDED &#8220;AS IS&#8221;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THIS SOFTWARE OR THE USE OR OTHER DEALINGS IN THIS&nbsp;SOFTWARE.</p>
<p>http://seoxys.com/azure-license/</p></blockquote>
<p><a href="http://dl.azuretalon.com/azure_license.txt">Plain text Azure&nbsp;License</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.seoxys.com/azure-license/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Sorry State of Apple Developer Relations</title>
		<link>http://www.seoxys.com/the-sorry-state-of-apple-developer-relations/</link>
		<comments>http://www.seoxys.com/the-sorry-state-of-apple-developer-relations/#comments</comments>
		<pubDate>Wed, 23 Sep 2009 19:54:42 +0000</pubDate>
		<dc:creator>kenneth</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Business]]></category>
		<category><![CDATA[Rants]]></category>

		<guid isPermaLink="false">http://www.seoxys.com/?p=229</guid>
		<description><![CDATA[iLaugh disappeared from the App Store about a week ago. My contract expired last&#160;week. I had been trying to renew the contract through the Apple Store for over a month now. However, I initially signed up through the Swiss Apple Store, and that is the only store it will let me&#160;use. The French Swiss store [...]]]></description>
			<content:encoded><![CDATA[<p>iLaugh disappeared from the App Store about a week ago. My contract expired last&nbsp;week.</p>
<p>I had been trying to renew the contract through the Apple Store for over a month now. However, I initially signed up through the Swiss Apple Store, and that is the only store it will let me&nbsp;use.</p>
<p>The French Swiss store is broken, and will not work at all. The German Swss store works, but will only accept a Swiss credit card. Thankfully, I do have one, but for some obscure reason, it throws an &ldquo;unexpected error&rdquo; every time I try to use it. It won&#8217;t let me use my US Bank of America cards at&nbsp;all.</p>
<p>I&rsquo;ve called and emailed Apple&rsquo;s support team many times. Yet all they tell me is that they&rsquo;ll forward it to some other team, which will (after waiting another week) email me proposing that I try &ldquo;emptying my browser&rsquo;s&nbsp;cache.&rdquo;</p>
<p>I&rsquo;m kind of unsure about what to do now. With every day that passes, I miss out on a substantial amount of money. Not only that, but not having the App in the Store causes many other problems, such as breaking links from my website, and&nbsp;more&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.seoxys.com/the-sorry-state-of-apple-developer-relations/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Apple&#8217;s Increasingly Ridiculous Rejections</title>
		<link>http://www.seoxys.com/apples-increasingly-ridiculous-rejections/</link>
		<comments>http://www.seoxys.com/apples-increasingly-ridiculous-rejections/#comments</comments>
		<pubDate>Thu, 11 Jun 2009 23:40:39 +0000</pubDate>
		<dc:creator>kenneth</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Business]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[Rants]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://www.seoxys.com/?p=195</guid>
		<description><![CDATA[Three months ago, I submitted an update to iLaugh and iLaugh Lite, numbered 1.1.1 that fixed many bugs but didn&#8217;t change anything to the functionality of the&#160;app. Today, after three whole months in review (seriously, I&#8217;m not making this up!), they decided to finally tackle the issue and issue me a rejection for no other [...]]]></description>
			<content:encoded><![CDATA[<p>Three months ago, I submitted an update to <a href="http://www.ilaughapp.com/">iLaugh</a> and iLaugh Lite, numbered 1.1.1 that fixed many bugs but didn&#8217;t change anything to the functionality of the&nbsp;app.</p>
<p>Today, after three whole months in review (seriously, I&#8217;m not making this up!), they decided to finally tackle the issue and issue me a rejection for no other reason other than &#8220;because we said&nbsp;so.&#8221;</p>
<p>See for&nbsp;yourself.</p>
<p><a href="http://akhun.com/seo/skitch/Inbox_%2821_messages%29-20090611-003253.png"><img src="http://akhun.com/seo/skitch/Inbox_%2821_messages%29-20090611-003253.png" /></a></p>
<p>Please note, this is for iLaugh 1.1.1. iLaugh 2.0 is still in review, as a new application, and there&#8217;s no reason it should be rejected. In fact, the premium edition has already been approved and is <a href="http://ilaughapp.com/appstore/premium.php">already live on the App&nbsp;Store</a>.</p>
<p>Speaking of iLaugh 2.0&thinsp;&#8211;&thinsp;the first public screenshot&nbsp;ever:</p>
<div style="text-align:center"><a href="http://ilaughapp.com/appstore/premium.php"><img src="http://akhun.com/seo/skitch/iPhone_Portrait_0708-20090609-183209.png" style="border:none;" /></a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.seoxys.com/apples-increasingly-ridiculous-rejections/feed/</wfw:commentRss>
		<slash:comments>90</slash:comments>
		</item>
		<item>
		<title>On The App Store Hype</title>
		<link>http://www.seoxys.com/on-the-app-store-hype/</link>
		<comments>http://www.seoxys.com/on-the-app-store-hype/#comments</comments>
		<pubDate>Sat, 30 May 2009 17:05:47 +0000</pubDate>
		<dc:creator>kenneth</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[Business]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Rants]]></category>

		<guid isPermaLink="false">http://www.seoxys.com/?p=189</guid>
		<description><![CDATA[A while back, TechCrunch covered yet another article complaining about the App Store being more of a Lotto than a marketplace. Setting aside the App&#160;Store&#8217;s numerous other issues, coverage of iPhone app developers has been divided into two extremes: reassuring yet unlikely success stories, or depressing yet much more likely failure&#160;stories. The general question in [...]]]></description>
			<content:encoded><![CDATA[<p>A while back, TechCrunch <a href="http://www.techcrunch.com/2009/05/25/the-app-store-hype-gets-a-dose-of-reality/">covered</a> yet another <a href="http://www.stromcode.com/2009/05/24/the-incredible-app-store-hype/">article</a> complaining about the App Store being more of a Lotto than a marketplace. Setting aside the App&#160;Store&#8217;s numerous other issues, coverage of iPhone app developers has been divided into two extremes: reassuring yet unlikely success stories, or depressing yet much more likely failure&nbsp;stories.</p>
<p>The general question in all of these articles is: &#8220;Can an average guy become a successful iPhone developer?&#8221;. The answer depends on how you define success, and on that topic I can speak from my own&nbsp;<a href="http://www.seoxys.com/growing-iphone-development-into-a-viable-business/">experience</a>.</p>
<p>If, to you, success means making a million bucks overnight you will most likely be unsuccessful. To me, success is defined as the return on my investment (both in time and money) on the project. In my <a href="http://www.seoxys.com/growing-iphone-development-into-a-viable-business/">previous article</a>, I mentioned making somewhere around a hundred dollars a day on iLaugh. However, I didn&#8217;t mention how much I invested in the&nbsp;project.</p>
<p>The first version of iLaugh and its subsequent revisions took me very little time to create. I estimate that I invested between ten to twenty hours of my time to create iLaugh 1.0. At my asking rate of $100 per hour, that represents a $1,000 to $2,000 investment. The server running the first iteration of the iLaugh API cost me about $100 per month to&nbsp;maintain.</p>
<p>If you look at the numbers for iLaugh from previous months, I make over $3,000 monthly (for a total of over $8,000 so far). Thus, I consider it a&nbsp;success.</p>
<p>Many people, in response to my previous article, said that I too, was one of the lucky ones, albeit on a smaller scale. And while that may be true, considering the low quality of that first iteration of iLaugh, a more carefully crafted app would likely have done&nbsp;better.</p>
<p><em>I believe the potential for success is relative to the investment put into&nbsp;anything.</em></p>
<p>If you look at the familiar success stories, many of them involve reinvestment and good marketing. For instance, <a herf="http://tapulous.com/">Tapulous</a> hit the jackpot with their Tap Tap games. Being good friends with one of their employees, I know exactly how much work goes into their&nbsp;production.</p>
<p>Perhaps one of the most talked-about success stories is Trism. Its developer, <a href="http://www.demiforce.com/games.html">Steve Demeter</a>, made an insane $250,000 in just two months. What I believe is the key to Steve&#8217;s long-term success, is that instead of buying a fancy sports car, he reinvested his money into founding a sustainable&nbsp;business.</p>
<p>Part of reinvesting, and a facet of development often ignored, are things that a typical developer <em>can&#8217;t</em> do. Most importantly: design, copywriting and marketing. These are things that will most likely have to be outsourced. Developers are reluctant to do that, because it&#8217;s very costly, but in the end, ignoring it is going to cost them the popularity of their&nbsp;application.</p>
<p>I view iLaugh 1.x as a catalyst towards bigger and, hopefully, even more successful&nbsp;endeavors.</p>
<p>In fact, I have already put a big part of my (in comparison to the numbers above, quite mediocre) earnings into the second iteration of iLaugh. I&#8217;ve hired a bunch of people much more talented than I am in their respective fields, and iLaugh 2.0 is coming along really nicely. It will be entirely different and nearly incomparable to the first iteration. There are some <em>very</em> cool things&nbsp;coming.</p>
<p>So, responding to my initial question: &#8220;Can an average guy become a successful iPhone developer?&#8221;. Yes! An average developer can be successful in the App Store. But it takes hard work, a lot of time, money, and&nbsp;perseverance.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.seoxys.com/on-the-app-store-hype/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Growing iPhone Development Into A Viable Business</title>
		<link>http://www.seoxys.com/growing-iphone-development-into-a-viable-business/</link>
		<comments>http://www.seoxys.com/growing-iphone-development-into-a-viable-business/#comments</comments>
		<pubDate>Wed, 08 Apr 2009 20:28:00 +0000</pubDate>
		<dc:creator>kenneth</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Business]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://www.seoxys.com/?p=155</guid>
		<description><![CDATA[When one hears stories from iPhone developers, they&#8217;re either from the lucky ones who made insane amounts of money and laugh all the way to the bank, or rather from disappointed developers who consider their efforts a&#160;failure. The latter tend to blame the App Store for the failure of their application(s). Granted, the App Store [...]]]></description>
			<content:encoded><![CDATA[<p>When one hears stories from iPhone developers, they&#8217;re either from the lucky ones who made insane amounts of money and laugh all the way to the bank, or rather from disappointed developers who <a href="http://www.techcrunch.com/2009/03/22/should-an-iphone-app-developer-charge-or-run-ads-galaxy-impact-case-study/">consider their efforts a&nbsp;failure</a>.</p>
<p>The latter tend to blame the App Store for the failure of their application(s). Granted, the App Store is a harsh market which has both its advantages and its flaws. But, in my humble opinion, a good craftsman never blames his&nbsp;tools.</p>
<p>The App Store has trends that can be analyzed, and if you&#8217;re going to be developing for the iPhone, you need to learn how to adapt. I have learnt this first-hand through experimentation, and have learnt many valuable lessons along the&nbsp;way.</p>
<p>Last September, while working on a much bigger iPhone game, I thought it would be cool to create a quick one-trick application for viewing jokes. I never envisioned that <a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=291699747&#038;mt=8">iLaugh</a> would become my most lucrative app that would keep me going while I develop the aforementioned&nbsp;game.</p>
<p><img src="http://akhun.com/seo/skitch/AppViz-20090408-213830.png" /></p>
<p>The Y-Axis shows daily revenue in US&nbsp;dollars.</p>
<p>Let&#8217;s leave the end of the graph (Feb-Apr) aside for a minute, we&#8217;ll get back to&nbsp;it.</p>
<p>You can see the initial release spikes, typical of the App Store, and then a very depressing downwards trend right after release. For the second release, 1.1, I upped the price from $0.99 to $1.99. Which slightly lowered the initial spike revenue. But at that stage, I had a much more mature app which unfortunately, due to lack of effective marketing stagnated at a sub-$20 daily&nbsp;revenue.</p>
<p>But in February, I made pretty much the best decision I have ever made. That, of course, was to release a Lite version. I initially thought it would be a nearly cost-free way to get some free advertising for the premium version. The main reason I put ads inside the Lite version was actually not to create revenue, but rather to give users a reason to upgrade. But, other than that, the Lite version was an identical, fully functional copy of the premium&nbsp;version.</p>
<p>As you can see, it did a pretty decent job of advertising the premium version. Since the mid-Feb release of iLaugh Lite, daily revenue for iLaugh has been much higher than it previously&nbsp;was.</p>
<p>Fortunately, <a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=305152278&#038;mt=8">iLaugh Lite</a> became quite popular on the iTunes App Store, and while never entering the global top 100, it has charted as high as #29 on the Entertainment chart, and has been in the top 40 entertainment apps nearly since its&nbsp;release.</p>
<p>While this did have some unexpected consequences, like bringing my entire server down due to excessive traffic which brought the iLaugh service down and forced me to upgrade to a better server, the benefits were pretty&nbsp;clear.</p>
<p><img src="http://akhun.com/seo/skitch/AppViz-20090408-215757.png" /></p>
<p>This graph shows daily iLaugh Lite&nbsp;downloads.</p>
<p>This equates to about 100,000 monthly&nbsp;downloads.</p>
<p>Here&#8217;s a graph that shows the web-service traffic this generates (since each joke is fetched from my server, this gives me a pretty good overview of the actual usage of the app). Unfortunately, I only started using this particular analytics package on March 2nd, so that&#8217;s when the graph&nbsp;starts.</p>
<p><img src="http://akhun.com/seo/skitch/Custom_Report_-_Google_Analytics-20090408-222008.png" /></p>
<p>To date, iLaugh has served over 6 million jokes, and it&#8217;s going at about one million per&nbsp;week.</p>
<p>So far I left out one pretty important thing: ad revenue. But one always leaves the best for last, right? So here&nbsp;goes:</p>
<p><img src="http://akhun.com/seo/skitch/skitched-20090408-221114.png" /></p>
<p>As the installed user-base for iLaugh Lite grows, so does daily ad revenue. Currently, I&#8217;m seeing pretty good numbers. I have around 6 million monthly ad impressions, and as you can see in the above graph, I&#8217;m seeing around $100 daily ad&nbsp;revenue.</p>
<p>While these aren&#8217;t mind-shattering numbers, I think they give a pretty good overview of what one can achieve as an average developer for the iPhone&nbsp;platform.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.seoxys.com/growing-iphone-development-into-a-viable-business/feed/</wfw:commentRss>
		<slash:comments>49</slash:comments>
		</item>
		<item>
		<title>How Genius is a Genius Business Model</title>
		<link>http://www.seoxys.com/how-genius-is-a-genius-business-model/</link>
		<comments>http://www.seoxys.com/how-genius-is-a-genius-business-model/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 15:34:45 +0000</pubDate>
		<dc:creator>kenneth</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Business]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[Internet]]></category>

		<guid isPermaLink="false">http://www.seoxys.com/?p=145</guid>
		<description><![CDATA[Apple&#8217;s introduction of Genius into iTunes may have been one of the best business decisions they ever&#160;made. First, it&#8217;s a great feature for the user. It&#8217;s a joy to just chose a beloved track, and instantly get plenty more of that awesomeness. I&#8217;ve been a great fan of Genius myself, and I use it all [...]]]></description>
			<content:encoded><![CDATA[<p>Apple&#8217;s introduction of Genius into iTunes may have been one of the best business decisions they ever&nbsp;made.</p>
<p>First, it&#8217;s a great feature for the user. It&#8217;s a joy to just chose a beloved track, and instantly get plenty more of that awesomeness. I&#8217;ve been a great fan of Genius myself, and I use it all the time. It&#8217;s also great when picking out tracks for a DJ&nbsp;set.</p>
<p>But what probably goes unnoticed by the general public is the staggering amounts of money Apple will be able to make of this. They will own the data to what millions of people are listening to. They&#8217;ll have direct access to millions of people&#8217;s tastes, likes, dislikes. Many companies would kill for such data, and I wouldn&#8217;t be surprised if the labels were prepared to pay big for such&nbsp;statistics.</p>
<p>Additionally, Apple is using genius to sell more music on the iTunes Store through the sidebar. The iTunes Store is already the biggest music retailer in the US, but with Genius, it&#8217;ll only sell even more music to the people already buying music on the&nbsp;store.</p>
<p>And lastly, Apple could sell promotions for artists who want more exposure for their music. Since Apple controls what users are exposed to / listen to when they&#8217;re in Genius, they can now push an artist more often in their user&#8217;s Genius lists, and thus give the user the impression and the feeling of liking the music. They can thus manipulate the user&#8217;s tastes, and I&#8217;m willing to bet that many record labels would pay big money for that kind of&nbsp;exposure.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.seoxys.com/how-genius-is-a-genius-business-model/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The MacHeist Argument™</title>
		<link>http://www.seoxys.com/the-macheist-argument/</link>
		<comments>http://www.seoxys.com/the-macheist-argument/#comments</comments>
		<pubDate>Wed, 25 Mar 2009 14:32:29 +0000</pubDate>
		<dc:creator>kenneth</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Rants]]></category>

		<guid isPermaLink="false">http://www.seoxys.com/?p=131</guid>
		<description><![CDATA[As another season of MacHeist comes, yet again the blogosphere is up in arms crying&#160;foul. A recent post by Marco Arment captured my&#160;attention. The argument has been done to death the first season, no need to go over it again. But there&#8217;s a few things so fundamentally wrong with his argument that I have to [...]]]></description>
			<content:encoded><![CDATA[<p>As another season of <a href="http://macheist.com">MacHeist</a> comes, yet again the blogosphere is up in arms crying&nbsp;foul.</p>
<p>A <a href="http://www.marco.org/89686877">recent post</a> by Marco Arment captured my&nbsp;attention.</p>
<p>The argument has been done to death the first season, no need to go over it again. But there&#8217;s a few things so fundamentally wrong with his argument that I have to call him out on&nbsp;it.</p>
<blockquote><p>It’s the usual Phill Ryu publicity stunt that will result in a bunch of blog attention, a few developers selling licenses at very steep discounts, and a token charitable donation to downplay the hundreds of thousands of dollars that Ryu will likely walk away&nbsp;with.</p></blockquote>
<p>Firstly, having worked with and for MacHeist personally, I can tell you first hand that it isn&#8217;t just a one-man show. There&#8217;s a much bigger team of Directorate, Coders, Designers and more, as you can see on their about page. Phill Ryu is best known as the public face of MacHeist, because it is his role. But by no means is it his own personal cash&nbsp;crop.</p>
<p>Secondly, specific numbers aside, donating 25% percent of revenues to charity is certainly not a &#8220;token donation.&#8221; A quarter of any revenue is not to be taken lightly. Now, granted it might be a marketing tool, but don&#8217;t let that negate the fact that charity does end up with a pretty huge donation in the end. MacHeist donated $500,000 last year, and this year looks like it might be getting a full&nbsp;million.</p>
<blockquote><p>a previous MacHeist offered developers about $5,000 per application for sales that eventually grossed over&nbsp;$300,000</p></blockquote>
<p>Now, this is just plain false. This is unconfirmed data and is based merely on rumors. It might very well have been the case, but do not parade it as fact, and do keep in mind that at the time a $5000 flat offer for an unknown business model that could very well end up in a flop was a pretty serious risk to take. The MacHeist guys did in fact claim that the numbers were much higher. Either way, this argument has gone back and forth enough the first&nbsp;season.</p>
<p>But the part that really gets on my nerves is&nbsp;this:</p>
<blockquote><p>Their developers can tell themselves that it’s a good deal and it’s worth eating the discount to gain&nbsp;exposure.</p></blockquote>
<p>We — and I say that as a developer who participated in a previous MacHeist bundle — are old enough to tell what&#8217;s good for us. What we especially don&#8217;t need is outsiders telling us we&#8217;re being ripped off. We&#8217;re running a serious business, and trust me when I say that we do not take such decisions lightly. What&#8217;s worse is that the person giving this argument is not even a Mac developer, according to his&nbsp;blog.</p>
<p>What you need to understand is that MacHeist is a business. We developers also run businesses. The keyword here is <b>business</b>. We don&#8217;t take these decisions on emotional value. We take these decisions because we judge that they will be beneficial to our businesses. We have to consider many things: The price of supporting and distributing thousands of licenses; (Please note that not all MacHeist sales actually mean an extra user for the developer. Many customers buy the bundle just for a specific app.) The actual (flat or percentage) monetary revenue we make out of it; The exposure we gain; The image this gives off the&nbsp;app.</p>
<p>Additionally, I&#8217;d like to prove this by giving the example of Gus Mueller. In the first season, he was offered a deal, which he declined, because he perceived it as a bad business decision. On the other head, he accepted the deal this time around with Acorn, because this time his perception of the new deal was&nbsp;different.</p>
<p>I have one thing to ask you, and that is not to believe when people tell you the developers are being ripped off. Rather make the decision to purchase the bundle on whether it has enough value for you to justify&nbsp;$39.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.seoxys.com/the-macheist-argument/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>App Store = Paperwork Nightmare</title>
		<link>http://www.seoxys.com/app-store-paperwork-nightmare/</link>
		<comments>http://www.seoxys.com/app-store-paperwork-nightmare/#comments</comments>
		<pubDate>Wed, 24 Sep 2008 13:16:29 +0000</pubDate>
		<dc:creator>kenneth</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[Business]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[Rants]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://www.seoxys.com/?p=92</guid>
		<description><![CDATA[[Note: I hope this article doesn&#8217;t break the NDA, but if it find out it does and I get a Cease &#038; Desist from Apple, I will have to take it&#160;down.] When you upload an iPhone application to the App Store through iTunes Connect, you&#8217;re presented with a few screens of information to fill in. [...]]]></description>
			<content:encoded><![CDATA[<p>[Note: I hope this article doesn&#8217;t break the NDA, but if it find out it does and I get a Cease &#038; Desist from Apple, I will have to take it&nbsp;down.]</p>
<p>When you upload an iPhone application to the App Store through iTunes Connect, you&#8217;re presented with a few screens of information to fill in. First, there&#8217;s the screen where you put the Application&#8217;s description, category, and any other textual information about&nbsp;it.</p>
<p>Then there&#8217;s the screen where you upload the binary, the icon(s), and screenshots. And lastly there&#8217;s a screen to set the price. Unlike what I thought would be the case, you cannot chose a specific price. You get to chose from several price groups. A price group has a price in US Dollars, and a price in different currencies usually of a similar value. (For example, a $0.99 app in Switzerland is CHF&nbsp;1.10)</p>
<p>At the top of this page, there is a little warning message that says you need a contract with Apple if you&#8217;re going to put up non-free apps. I did not pay too much attention to it, and the rest of the process seemed to go smoothly, eventually leading back to a page where I could see my app was &#8220;In&nbsp;Review&#8221;.</p>
<p>I was still slightly confused about this contract message, and decided to find out what it was about. I asked a few fellow developers, and found out that Apple would not sell my app until the contract was taken care&nbsp;of.</p>
<p>In iTunes Connect, there is a section on contracts, with a link to create a new contract. A contract is made of three parts; Contact Details, Banking Details and Tax&nbsp;Details.</p>
<ul>
<li><b>Contact Details</b>
<p>This is very straightforward. I just had to fill in my full contact details. (Including physical&nbsp;address.)</li>
<li><b>Banking Details</b>
<p>This is slightly more complicated. I&#8217;m with one of the smaller Swiss banks, and I wanted to use this account for my App Store&nbsp;revenue.</p>
<p>One of the things Apple requires is a SWIFT code. Luckily, I&#8217;m with a Swiss bank, and these tend to be very professional. I just had to give my bank a phone call, and I had my SWIFT code. However, after reading a recent topic on the MacSB mailing list, it appears to be very common for many of the smaller banks in the US and other countries not to have SWIFT codes. In which case you&#8217;re screwed and you&#8217;ll have to open a new account with a bank that has a SWFT code. (Apple recommends Bank of&nbsp;America.)</p>
<p>Another thing required by Apple is the IBAN. International Bank Account Number. My bank informed me that they printed these on all the bank statements they issued. However, I didn&#8217;t have any bank statement around. It wasn&#8217;t too hard getting this number. Switzerland has a standardized way of building these numbers from your CB Number (Clearing Banquaire - this is what we call Branch IDs) and your account number. A handy little script I found on the web would take this info and convert it into an IBAN. (I later found one of my Bank statements, and the IBAN generated did indeed match the one on the&nbsp;statement).</p>
<p>Apple also asked for the Branch ID (I put my CB number for this) and account number, and another number called the SIC / Short Code. I researched it a bit, and it looks like I didn&#8217;t need it. I just left that field&nbsp;blank.</li>
<li><b>Tax Details</b>
<p>This is where it gets nasty. Note that this is not an Apple thing, this is government tax regulation. Apple provides an online version of the government form W-8BEN. It seems I am not obligated to fill this form in, but if I don&#8217;t, Apples keeps another 30% of my revenue as anticipated taxes. This, with the 30% commission they take from every sale, leaves me with only 49% of my gross sales. (70% * 70% =&nbsp;49%)</p>
<p>This form is extremely cryptic, and I filled it in to the best of my knowledge. This, however, wasn&#8217;t enough for Apple. The form complained about missing information. It&#8217;s only then that I realized that Apple provides a handy tip sheet explaining how to fill the form in, and what are the most common&nbsp;answers.</p>
<p>With this information, I was able to understand and fill in most of the form. Except for one field: Taxpayer Identification Number. Since I&#8217;m not a US resident (although I&#8217;m eligible for citizenship by blood, and plan to apply soon), I did not have this information. Apple&#8217;s tip sheet luckily had a small paragraph regarding this. An EIN (Employer Identification Number) would do. To get an EIN, I had to download another form entitled&nbsp;SS-4.</p>
<p>This form was even more cryptic than the previous one. It is obviously made for more traditional companies, and had questions asking how many employees I have in different field, how much wages I paid them, where and when my company was incorporated, and a bunch of other tax-related questions. It also asked a few things I couldn&#8217;t fill in, such as my SSN (Social Security Number - I don&#8217;t have one). I phoned the IRS (Internal Revenue Service) - the government entity I had to submit the form to - and it turned out this field wasn&#8217;t necessary. In response to the question &#8220;Check one box that best describes the principal activity of your business&#8221;, there of course wasn&#8217;t anything about technology. I had to tick &#8220;Other (specify)&#8221; and enter&nbsp;&#8220;Royalties&#8221;.</p>
<p>There is three way you can submit the form. Firstly, you can do it the traditional way of mailing it by post. But this would take a minimum of 4 weeks. Second way would be by fax, but this would also take at least 1 week. The third way is actually pretty clever. You fax while you&#8217;re on the&nbsp;phone.</p>
<p>Problem: my phone and my fax are on the same phone line. Meaning I can&#8217;t do both at the same time. I do have a cellphone, but phoning oversees for a good half hour at least from a cellphone would be so outrageously expensive it didn&#8217;t make any sense. Luckily, I though of a brilliant idea, and opened a Skype Out account. The audio quality wasn&#8217;t very good, but at least it worked. After another hour of phoning, I finally had my EIN and could submit the W-8BEN form to&nbsp;Apple.</li>
</ul>
<p>Everything seems to be in order as of now. My app is still in review, but expect it in the app store&nbsp;soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.seoxys.com/app-store-paperwork-nightmare/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Registration Schemes: Asymmetrical Cryptography</title>
		<link>http://www.seoxys.com/registration-schemes-asymmetrical-cryptography/</link>
		<comments>http://www.seoxys.com/registration-schemes-asymmetrical-cryptography/#comments</comments>
		<pubDate>Sat, 05 Apr 2008 22:13:05 +0000</pubDate>
		<dc:creator>kenneth</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Business]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.seoxys.com/?p=86</guid>
		<description><![CDATA[One challenge that most developers face when nearing release of their first application is how to implement registration and piracy protection. This three-part article will describe three common types of registration schemes: Serial Numbers, Asymmetrical Cryptographic Keys and Product&#160;Activation. Part Two: Asymmetrical&#160;Cryptography Asymmetrical Cryptographic Keys are a great way to secure you app, because the [...]]]></description>
			<content:encoded><![CDATA[<p>One challenge that most developers face when nearing release of their first application is how to implement registration and piracy protection. This three-part article will describe three common types of registration schemes: <b>Serial Numbers</b>, <b>Asymmetrical Cryptographic Keys</b> and <b>Product&nbsp;Activation</b>.</p>
<hr />
<h1>Part Two: Asymmetrical&nbsp;Cryptography</h1>
<p>Asymmetrical Cryptographic Keys are a great way to secure you app, because the code used to generate serials is not included in your app, thus removing the risk of a keygen. Using a private key, you sign (or encrypt) some of the user&#8217;s details. You then use this singed data as the key to your software, either in the form of a serial, a file, or even <a href="http://switchersblog.com/2007/04/05/license-keys-mac-style-1passwd-introduces-new-license-cards.html">an image with the data embedded</a>. You then verify that the signature is valid using the public key in your&nbsp;app.</p>
<p><b>Example</b></p>
<p>Start off by generating a set of private and public RSA keys. You can do this by using the following in&nbsp;Terminal.app:</p>
<p><code>openssl genrsa -out private.pem 2048<br />
openssl rsa -in private.pem -out public.pem -outform PEM&nbsp;-pubout</code></p>
<p>You can use different size keys. Using a shorter key, such as 512 will make your software more vulnerable to brute-force attack, but has the advantage of making the signature smaller (Which is useful if you wish to display it in the form of a Serial&nbsp;Number).</p>
<p>I believe I used the following set of keys. The keys are also included as files in the source code of this example (available at the bottom of this&nbsp;article).</p>
<p><code>-----BEGIN RSA PRIVATE KEY-----<br />
MIIEpAIBAAKCAQEAwKhjrkHmaupDGERSHdgZuSwBWBr4kufBGz0Dk5sn3PR3ZtaP<br />
Vrv6+5Mdz1gAEBYbUVH3m+4+dHcwol5xNckKBT8M5Zy6GPoV9dBUS/1wQBzgdTzf<br />
jvV4uE9S0pofQWw3faZ904tTOjbM0qUko2nd7yyjYBhh/m1ABEFHuL62BvRp13na<br />
vv6534OqqeExEb9VD3K9+Rr4+YQVRUpqZSz2xwhqfLgAzFVQ9bmSG8yTVKmF/vQA<br />
t+N8ThN2WO5qYtCbPawkmIpwvUCTXkxAiiTPNOiU3G1vwtzBoma9TL6dgGmhq6P7<br />
0KBcQNGUEpA2PFC7MEBeNyVyiMIOAvrkHjY/VQIDAQABAoIBABUNET9EMiIykLxB<br />
Etvx9fWWylrPL6QVsLMCOrbROEzbZYSWIzlt9uGwVIyIaBFZ6Qg8tZqTML3XHDhR<br />
q3seCXtDRWx9cJQ0F1wxtFRNUAuhXCFTUnYzekphWIJslse2RGX1YEBSM/jjbgQC<br />
SXuVoMt2jC9+2o5Lb7hHTcfxBsDBmZpghArT5seTOwDOOhTULqoh2wgZYB2IpgTI<br />
UV2CPpAqRVECRnPNdE5UcNIeHc7g4aji5BO0G0u8uM4RUffuRcLaPymuxpU9vwd1<br />
gjVaG6BF/2odW7GEBU3FNLUtvr9MxT+HC+hwOJUuk8NWxU7DqMdyiwSs7W3Nnx7R<br />
5RPvj8ECgYEA34DZjy5EMm7QyPZA6DvAZv6RIecFEwEkwFG+mQgoCy4VfLikkwzC<br />
bI8M8fc6Xiix7ZTjSmvuHt1D4HSRHMOVYgDzY0A5+F+8X657mN5TwNlYMOUkDX3I<br />
rNwc3cRVqtLZYGX0H7cR6eEomGJ7fA9gKuTpaXI0IJz5DsqsgTaGvfECgYEA3Ktr<br />
Q53i52jnssL9c3JsxQO+I/2fWKgo3bZeBI/5zLsz3itVjFjMVldrIK1QZWXI4z7l<br />
dPYwh6qCa1unsizuuzeAhW6NcuUjGPBlBqlo/a9WfOo16ExPXBoH3PH2DXz/YS+D<br />
DOp4Wl8ePhO7C46t3zmGahchysx3kCGkAmNkA6UCgYEA0upvZNUOemFlGiB5RC8O<br />
9KMLJukyOqr7mZoKubOexl4o3NgKRtLlrziXyMe8Bxt0PXYhwBt2TR4Vbf3S60gO<br />
8rte86yqiB8gT1MDRFGazATPWuUCTtECzU2y1/ztsxTjGjtcU4mZmBJpEtTtHzgL<br />
Uq9PLbkeRCCeUD0m6ZEhOqECgYB85jFyNh1F6aSrE56tB2j1Iicu69CTN6rZwuz4<br />
HB3BeXvkFhb3txMBE7244yAMJE5OAT2Ss/3H7AShi2EhgjklkkaWP3qkO3lgFkC4<br />
Qo8Ad4u2bEJS105bzQgCUJl6DPPnKCM+3j98tzXA4R4PbpSPMloYFju0M4LA+6l/<br />
CI6FWQKBgQCWr4Py/GBhgoYOlY/f41NzOfsttwcCBum3uPbiPq6gM/AQQRjzdUmK<br />
QRgG9XXs/33KUMiU+/15hK8ShrOWRSx+zHdgeMhVmuYJdEeygANI9dkonJ3+Olth<br />
77beMQrKIY9kw4bVRFtLWhxfAHXvnksnBg79PX05joVvoHFgVxuwlg==<br />
-----END RSA PRIVATE KEY-----<br />
-----BEGIN PUBLIC KEY-----<br />
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwKhjrkHmaupDGERSHdgZ<br />
uSwBWBr4kufBGz0Dk5sn3PR3ZtaPVrv6+5Mdz1gAEBYbUVH3m+4+dHcwol5xNckK<br />
BT8M5Zy6GPoV9dBUS/1wQBzgdTzfjvV4uE9S0pofQWw3faZ904tTOjbM0qUko2nd<br />
7yyjYBhh/m1ABEFHuL62BvRp13navv6534OqqeExEb9VD3K9+Rr4+YQVRUpqZSz2<br />
xwhqfLgAzFVQ9bmSG8yTVKmF/vQAt+N8ThN2WO5qYtCbPawkmIpwvUCTXkxAiiTP<br />
NOiU3G1vwtzBoma9TL6dgGmhq6P70KBcQNGUEpA2PFC7MEBeNyVyiMIOAvrkHjY/<br />
VQIDAQAB<br />
-----END PUBLIC KEY-----<br />
</code></p>
<p>Next, we will create the generator. We will start by concatenating the details (full name and email address) into a single&nbsp;string:</p>
<p><code>First&nbsp;Last+email@address.com</code></p>
<p>Then, we will use RSA to sign this string using the private key generated&nbsp;above:</p>
<p><code>lFZpwJ6GPLXz8sDez033RIxJsN072lOEa0qF+8hQ5KCcZEPQqSBU4MKbW+UJxIfSmKMOBYnVfy/wwAoSxTtqn2JIuAPEJvsTlb0mGH5u7mpxH+FDj2TicoBKephWv7UXP9k10OPA45247+j/u4yKT1UZcq7WjChQ3JoE3wBtEoFucQm8vLk/VqvNaBM1TyNEgwT8FmrKlbK1FNUI8nQ0QOEJ9P8oMAblkWE5kALZZqWnAs6xE7c73sex73t5FvxYRqRDzRDzkjTwK0anXCv8dmeLvnaaHAFcfD5llx09oa89q+wzWucE7V1TsPRYKH1sZsSz5G2xTt2pZrjIoTw5ew==</code></p>
<p><b>Note</b>: for this sample app, I explicitly turned off creating newlines in the base64&nbsp;signature.</p>
<p>The code used for this generator&nbsp;is:</p>
<pre class="textmate-source"><span class="source source_objc"><span class="meta meta_implementation meta_implementation_objc"><span class="meta meta_scope meta_scope_implementation meta_scope_implementation_objc"><span class="meta meta_function meta_function_objc">-<span class="meta meta_return-type meta_return-type_objc"><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="storage storage_type storage_type_objc">IBAction</span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="entity entity_name entity_name_function entity_name_function_objc">generate</span></span><span class="meta meta_argument-type meta_argument-type_objc"><span class="entity entity_name entity_name_function entity_name_function_name-of-parameter entity_name_function_name-of-parameter_objc"><span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="storage storage_type storage_type_objc">id</span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_objc">sender</span></span>
</span>{
    <span class="support support_class support_class_cocoa">NSData</span> *privateKeyData = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span><span class="support support_class support_class_cocoa">NSData</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">dataWithContentsOfURL<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span><span class="support support_class support_class_cocoa">NSURL</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">fileURLWithPath<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span><span class="support support_class support_class_cocoa">NSBundle</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">mainBundle</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">pathForResource<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>private<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span> <span class="support support_function support_function_any-method support_function_any-method_name-of-parameter support_function_any-method_name-of-parameter_objc">ofType<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>pem<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span>;
    <span class="support support_class support_class_cocoa">NSData</span> *publicKeyData = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span><span class="support support_class support_class_cocoa">NSData</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">dataWithContentsOfURL<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span><span class="support support_class support_class_cocoa">NSURL</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">fileURLWithPath<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span><span class="support support_class support_class_cocoa">NSBundle</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">mainBundle</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">pathForResource<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>public<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span> <span class="support support_function support_function_any-method support_function_any-method_name-of-parameter support_function_any-method_name-of-parameter_objc">ofType<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>pem<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span>;
    <span class="support support_class support_class_cocoa">NSString</span> *details = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span><span class="support support_class support_class_cocoa">NSString</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">stringWithFormat<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>%@+%@<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span>, <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span>name <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">stringValue</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span>, <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span>email <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">stringValue</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span>;

    SSCrypto *crypto = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span>SSCrypto <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">alloc</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">initWithPublicKey<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>publicKeyData <span class="support support_function support_function_any-method support_function_any-method_name-of-parameter support_function_any-method_name-of-parameter_objc">privateKey<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>privateKeyData</span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span>;
    <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span>crypto <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">setClearTextWithString<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>details</span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span>;

    <span class="support support_class support_class_cocoa">NSData</span> *signedTextData = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span>crypto <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">sign</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span>;
    <span class="support support_class support_class_cocoa">NSString</span> *string = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span>signedTextData <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">encodeBase64WithNewlines<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="constant constant_language constant_language_objc">NO</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span>;

    <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span>serial <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">setStringValue<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>string</span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span>;

    <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span>crypto <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">release</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span>;
}
</span></span></span></pre>
<p>As you can see, I used Septicus Software&#8217;s great <a href="http://septicus.com/products/opensource/">SSCrypto</a> framework for this task&#8230; It makes things so much easier&#8230; Unfortunately it doesn&#8217;t support base32 or DSA, which would both have helped make more human-friendly&nbsp;keys.</p>
<p>The other piece needed is the validator, used in your software to validate serial numbers. Include only the public key in your app, and use RSA to verify the&nbsp;key.</p>
<pre class="textmate-source"><span class="source source_objc"><span class="meta meta_implementation meta_implementation_objc"><span class="meta meta_scope meta_scope_implementation meta_scope_implementation_objc"><span class="meta meta_function meta_function_objc">-<span class="meta meta_return-type meta_return-type_objc"><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="storage storage_type storage_type_objc">IBAction</span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="entity entity_name entity_name_function entity_name_function_objc">validate</span></span><span class="meta meta_argument-type meta_argument-type_objc"><span class="entity entity_name entity_name_function entity_name_function_name-of-parameter entity_name_function_name-of-parameter_objc"><span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">(</span><span class="storage storage_type storage_type_objc">id</span><span class="punctuation punctuation_definition punctuation_definition_type punctuation_definition_type_objc">)</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_objc">sender</span></span>
</span>{
    <span class="support support_class support_class_cocoa">NSData</span> *publicKeyData = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span><span class="support support_class support_class_cocoa">NSData</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">dataWithContentsOfURL<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span><span class="support support_class support_class_cocoa">NSURL</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">fileURLWithPath<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span><span class="support support_class support_class_cocoa">NSBundle</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">mainBundle</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">pathForResource<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>public<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span> <span class="support support_function support_function_any-method support_function_any-method_name-of-parameter support_function_any-method_name-of-parameter_objc">ofType<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>pem<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span>;
    <span class="support support_class support_class_cocoa">NSString</span> *details = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span><span class="support support_class support_class_cocoa">NSString</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">stringWithFormat<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>%@+%@<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span>, <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span>name <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">stringValue</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span>, <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span>email <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">stringValue</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span>;
    <span class="support support_class support_class_cocoa">NSData</span> *number = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span>serial <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">stringValue</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">dataUsingEncoding<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="support support_constant support_constant_cocoa">NSUTF8StringEncoding</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">decodeBase64WithNewLines<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span><span class="constant constant_language constant_language_objc">NO</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span>;

    SSCrypto *crypto = <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span>SSCrypto <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">alloc</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">initWithPublicKey<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>publicKeyData</span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span>;
    <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span>crypto <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">setCipherText<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>number</span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span>;

    <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span>crypto <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">verify</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span>;

    <span class="keyword keyword_control keyword_control_c">if</span>(<span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span><span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span>crypto <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">clearTextAsString</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">isEqualToString<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>details</span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span>)
        <span class="support support_function support_function_cocoa">NSRunAlertPanel</span>(<span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>Result<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span>, <span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>Good serial!<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span>, <span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>OK<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span>, <span class="constant constant_language constant_language_objc">nil</span>, <span class="constant constant_language constant_language_objc">nil</span>);
    <span class="keyword keyword_control keyword_control_c">else</span>
        <span class="support support_function support_function_cocoa">NSRunAlertPanel</span>(<span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>Result<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span>, <span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>Wrong serial!<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span>, <span class="string string_quoted string_quoted_double string_quoted_double_objc"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_objc">@"</span>OK<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_objc">"</span></span>, <span class="constant constant_language constant_language_objc">nil</span>, <span class="constant constant_language constant_language_objc">nil</span>);

    <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">[</span>crypto <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">release</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_objc">]</span></span>;
}
</span></span></span></pre>
<p><b>Important Note</b>: In this sample code, I included both the generator and the validator in the same application. I included the private.pem file in the bundle. You should <b>never</b> do this. If the private key is ever leaked, it compromises the whole security of your&nbsp;application.</p>
<p><b>Making it&nbsp;safer</b></p>
<p>You can easily make it more secure by combining this technique with the technique explained in Part One. Instead of simple concatenating the details as I did here, you could use all the techniques applied in Part One, such as using a hash instead, or doing ROT13 on it, or rearranging the order of the&nbsp;characters.</p>
<p>Another thing you should do is to hardcode and obfuscate your public key. Having it as a file in the bundle makes you vulnerable to key substitution. (Basically, a cracker would replace the public key in your app by a different key they created using a private key they know, thus making their licenses valid instead of&nbsp;yours.) </p>
<p><b>Form&nbsp;Factors</b></p>
<p>While you may not realize it at first sight, this has become one of the most common methods in Mac shareware, thanks to the open-source framework <a href="http://aquaticmac.com">AquaticPrime</a>. AquaticPrime uses this technique behind the scenes, by embedding the signature in a plist file. AquaticPrime is a very easy way to use this. Unfortunately, if you decide to use AquaticPrime.framework in your app, it is very easy to replace the .framework file with a malicious one that will always claim your licenses are&nbsp;valid.</p>
<p>To date, as far as I know, there isn&#8217;t any HackuaticPrime.framework yet, but this might one day become a problem with AquaticPrime gaining popularity thanks to it&#8217;s extreme simplicity of&nbsp;implementation.</p>
<p><b>Update</b>: <b>Devon</b> in the comments suggests implementing a hash check of the framework, which is a simple way of checking the framework&#8217;s integrity. Of course, there are still ways to get around it, but this makes it one step more&nbsp;difficult.</p>
<p>Another common form factor for Asymmetrical Cryptographic Keys is custom URL schemes. That&#8217;s actually a very clever and convenient way of doing it. To register, the users get to simple click on a link which looks like this: (All the user sees is a nice &#8220;Click here to register&#8221;&nbsp;link)</p>
<p><code>myapp://name:email:key</code> </p>
<p>Another clever, but controversial form factor is Agile Web Solution&#8217;s 1Password <a href="http://switchersblog.com/2007/04/05/license-keys-mac-style-1passwd-introduces-new-license-cards.html">License&nbsp;&#8220;Cards&#8221;</a>.</p>
<p>And of course, if you find a way to make short base32 signatures (I hear DSA makes short signatures), you can even use longer Serial&nbsp;Numbers.</p>
<p><code>AHJ53-5HGJZ-8DG8R-284DF-56FJB-74FH4-FJUEH</code></p>
<hr />
<p><b>Sample&nbsp;Code</b></p>
<p>The code used in this article can be downloaded <a href="http://dl.azuretalon.com/async.zip">here</a>.<br />
As always, licensed under MIT license. If you do use it, mention it in the About Box or&nbsp;readme.txt.</p>
<hr />
<p><a href="http://www.seoxys.com/registration-schemes-serial-numers/">Part One: Serial Numbers</a><br />
The next part will be coming&nbsp;soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.seoxys.com/registration-schemes-asymmetrical-cryptography/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Registration Schemes: Serial Numbers</title>
		<link>http://www.seoxys.com/registration-schemes-serial-numers/</link>
		<comments>http://www.seoxys.com/registration-schemes-serial-numers/#comments</comments>
		<pubDate>Thu, 03 Apr 2008 21:26:56 +0000</pubDate>
		<dc:creator>kenneth</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Business]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[Hacking]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.seoxys.com/?p=85</guid>
		<description><![CDATA[One challenge that most developers face when nearing release of their first application is how to implement registration and piracy protection. This three-part article will describe three common types of registration schemes: Serial Numbers, Asymmetrical Cryptographic Keys and Product&#160;Activation. Part One: Serial&#160;Numbers Serial numbers are the simplest, most practical option. However, they are also the [...]]]></description>
			<content:encoded><![CDATA[<p>One challenge that most developers face when nearing release of their first application is how to implement registration and piracy protection. This three-part article will describe three common types of registration schemes: <b>Serial Numbers</b>, <b>Asymmetrical Cryptographic Keys</b> and <b>Product&nbsp;Activation</b>.</p>
<hr />
<h1>Part One: Serial&nbsp;Numbers</h1>
<p>Serial numbers are the simplest, most practical option. However, they are also the least secure. It consists of taking at least one of the customers&#8217; details, and creating a serial number from it. The serial number is usually tied to either the customer&#8217;s name, or his email address, preferably&nbsp;both.</p>
<p>For example, let&#8217;s say the customer&#8217;s name &#8220;First Last&#8221; and his email address is &#8220;email@address.com&#8221;. The first step would be to strip his name and email address of any non-alphabetical characters, concatenate it and convert it to uppercase. (I put the email address first, because it&#8217;s less recognizable) Here&#8217;s what we&nbsp;get:</p>
<p><code>EMAILADDRESSCOMFIRSTLAST</code></p>
<p>Now map this string onto a XXXX-XXXX-XXXX-XXXX-XXXX key. If there are any character leftovers, just discard them. If there aren&#8217;t enough characters to fill all the Xs in, leave them as something constant. (they don&#8217;t have to be all the same, but they have to be the same for each position all the time. You could for example say you&#8217;re mapping it onto an QRST-ABCD-IJLK-EFGH-MNOP key, and leave unfilled spaces as&nbsp;is)</p>
<p><code>EMAI-LADD-RESS-COMF-IRST</code></p>
<p>Then, we&#8217;d apply ROT13 on&nbsp;it.</p>
<p><code>RZNV-YNQQ-ERFF-PBZS-VEFG</code></p>
<p>Lastly, we could replace any swearwords in the key by some random other constant text, <a href="http://www.rogueamoeba.com/utm/posts/Random/RASN2-Swears-2007-10-16-15-00.html">just in&nbsp;case</a>.</p>
<p>Another example, using a similar method: Using the same customer, here&#8217;s what we&#8217;d do. Take his details, concatenate and salt&nbsp;them:</p>
<p><code>First Last+random&nbsp;salt+email@address.com</code></p>
<p>Then, MD5 the result and add another&nbsp;salt:</p>
<p><code>salt+0fb61d4a0f894c63d3ddbd8388404b6c</code></p>
<p>Next, SHA1 the&nbsp;result:</p>
<p><code>28a8275bdcbca542f567efef9cc4db2150c38900</code></p>
<p>And finally, uppercase it and map it onto a XXXX-XXXX-XXXX-XXXX-XXXX&nbsp;serial:</p>
<p><code>28A8-275B-DCBC-A542-F567</code></p>
<p>When you have decided on a serial scheme, implementing it is easy. Upon registration, you take the buyer&#8217;s name and email address, and generate a serial from it. He then has to input this serial into you app, along with his name and email address. All you have to do in you app is take the name and email address he gave you, generate a serial from it, and check it against the serial he gave&nbsp;you.</p>
<p><b>Making it more&nbsp;secure</b></p>
<p>For security reasons, one important step to take is obfuscating how you create those serials, in case anyone tries to create a keygen for you app. The easiest way is adding dummy maths code in the middle of the code where you work out your serial. It will not affect your serial, but it will show up in the assembly code in case anyone tries to gdb your app (more on that in another blog post I have&nbsp;planned).</p>
<p>Another quick thing you could do is shuffle the characters a bit on a set pattern to make them less&nbsp;obvious.</p>
<p>For example you could use this&nbsp;pattern:</p>
<p><code>ABCD-EFGH-IJKL-MNOP-QRST</code></p>
<p>becomes</p>
<p><code>TMLN-DQGA-ISPC-BEOK-FJRH</code></p>
<p><b>Stand-alone&nbsp;serials</b></p>
<p>Sometimes, your serials cannot be tied to any of the customer&#8217;s data, for example for retail sales. In that case, you&#8217;d need a different serial scheme. You need to choose certain characteristics / rules that make a serial valid. It could be as simple as checking that the 19th character is a&nbsp;W.</p>
<p>Here&#8217;s a set of example rules you could&nbsp;use:</p>
<ul>
<li>The ASCII value of the first character of all five blocks of four characters have to add up to&nbsp;100.</li>
<li>The last character of all five blocks of four characters have to be&nbsp;vowels.</li>
<li>The first character of either block 3 or 4 has to be&nbsp;E.</li>
<li>The ASCII value to the third character of every block have to be even&nbsp;numbers.</li>
</ul>
<p>In your apps, just check the serial against the rules, and if it&#8217;s correct, you can assume it is a correct&nbsp;serial.</p>
<p>For your generator, you can have a pre-made list of valid serials, and assign them to a customer or print them on a retail copy when needed. The problem with this method is that you can eventually run out of valid serials. In which case you would have to generate a new batch of serials, or reassign already used serials to a second&nbsp;customer.</p>
<p>Another (better) way of doing stand-alone serial numbers is splitting the serial number in two, and basing the second part on the first part. [thanks to <b>tomasf</b> from the <a href="irc://irc.freenode.net/#macsb">#macsb</a> IRC channel for this&nbsp;method]</p>
<p>For example, in a serial number ABCD-EFGH-D07A-A959-F269, separate the first eight characters from the rest of the&nbsp;serial:</p>
<p><code>ABCDEFGH</code> </p>
<p>Salt&nbsp;it:</p>
<p><code>saltyABCDEFGH+123</code></p>
<p>MD5:</p>
<p><code>d07aa959f269104ab28e2a748c415c5c</code></p>
<p>Map it onto&nbsp;XXXX-XXXX-XXXX:</p>
<p><code>D07A-A959-F269</code></p>
<p>And check it against the second part of the serial. In this example, the serial is&nbsp;correct.</p>
<hr />
<p><a href="http://www.seoxys.com/registration-schemes-asymmetrical-cryptography/">Part Two: Asymmetrical Cryptographic Keys</a><br />
The last parts will be coming&nbsp;soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.seoxys.com/registration-schemes-serial-numers/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

