<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8091209</id><updated>2011-12-15T03:55:12.323+01:00</updated><title type='text'>Selvatech.com : in the jungle of financial I.T.</title><subtitle type='html'>&lt;b&gt;Goal&lt;/b&gt; : Log I.T. technical issues and solving.&lt;br&gt;
&lt;b&gt;Areas&lt;/b&gt; : .Net programming, financial algorithmics...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ittech.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8091209/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://ittech.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Bertrand</name><uri>http://www.blogger.com/profile/11449343555146205550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bpujos.free.fr/bp_small.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>2</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8091209.post-111989401017101325</id><published>2005-06-27T19:27:00.000+02:00</published><updated>2005-06-30T19:41:51.740+02:00</updated><title type='text'>An in-depth examination of Yahoo! Financial Web Services</title><content type='html'>&lt;span style="font-size:85%;"&gt;As I was building a statistical tools on stock quotes, I realized that I didn't find any reliable source or article describing the services provided by Yahoo! Finance.&lt;br /&gt;&lt;br /&gt;I am using these services for three years now, and I have to admit that it is one of the best tool for anyone working on stock quotations (all over the world) and... it's free (massive argument for testing) !! There are so many data sources (Telekurs, Comstock...), that it's best to have a look and try to see wich company provides it.&lt;br /&gt;&lt;br /&gt;All datas are available on web page (see &lt;/span&gt;&lt;a href="http://finance.yahoo.com/q?s=GE"&gt;&lt;span style="font-size:85%;"&gt;http://finance.yahoo.com/q?s=GE&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; for a summary of financial information on stock code GE : General electric for example), some datas are available as Excel spreadsheet download, and, finally, some datas are available as "Web Services". Well, it's more a proprietary service on internet than a Web Services (no web service description file...).&lt;br /&gt;&lt;br /&gt;I will go into details about 3 services : quotation service, index components service and historical data service. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;em&gt;&lt;strong&gt;Quotation Web Service&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;As you can see on &lt;/span&gt;&lt;a href="http://finance.yahoo.com/q?s=GE"&gt;&lt;span style="font-size:85%;"&gt;http://finance.yahoo.com/q?s=GE&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; page, there is a small "Download data" link. This link will download a CSV file using the hyperlink &lt;/span&gt;&lt;a href="http://finance.yahoo.com/d/quotes.csv?s=GE&amp;f=sl1d1t1c1ohgv&amp;amp;e=.csv"&gt;&lt;span style="font-size:85%;"&gt;http://finance.yahoo.com/d/quotes.csv?s=GE&amp;f=sl1d1t1c1ohgv&amp;amp;e=.csv&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; .&lt;/span&gt; &lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;The data received look like the following :&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;GE,34.74,"6/27/2005","1:25pm",-0.04,34.72,34.86,34.60,14050200&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;Let's try to understand how it works :&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;Obviously the GE parameter in the URL (s=GE) is related to the stock code, in fact on New Yorck Stock Exchange, General electric stocks are symbolized by GE code. You will notice that the quotation place is not showed. You can write comma separated stock quotes to retrieve several quotations at the same time. For example : &lt;a href="http://finance.yahoo.com/d/quotes.csv?s=GE,MSFT&amp;f=sl1d1t1c1ohgv&amp;amp;e=.csv"&gt;http://finance.yahoo.com/d/quotes.csv?s=GE,MSFT&amp;f=sl1d1t1c1ohgv&amp;amp;e=.csv&lt;/a&gt; .&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;Once the stock code is references, the f parameter is a long string composed of letters and figures. Strangely, I found no web site describing precisely these parameters. I found their meaning empirically :&lt;br /&gt;&lt;br /&gt;&lt;table border="1"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td&gt;a&lt;/td&gt;&lt;td&gt;Ask&lt;/td&gt;&lt;td&gt;a2&lt;/td&gt;&lt;td&gt;Average Daily Volume&lt;/td&gt;&lt;td&gt;a5&lt;/td&gt;&lt;td&gt;Ask Size&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;b&lt;/td&gt;&lt;td&gt;Bid&lt;/td&gt;&lt;td&gt;b2&lt;/td&gt;&lt;td&gt;Ask (Real-time)&lt;/td&gt;&lt;td&gt;b3&lt;/td&gt;&lt;td&gt;Bid (Real-time)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;b4&lt;/td&gt;&lt;td&gt;Book Value &lt;/td&gt;&lt;td&gt;b6&lt;/td&gt;&lt;td&gt;Bid Size&lt;/td&gt;&lt;td&gt;c&lt;/td&gt;&lt;td&gt;Change &amp; Percent Change &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;c1&lt;/td&gt;&lt;td&gt;Quotation Net Change&lt;/td&gt;&lt;td&gt;c3&lt;/td&gt;&lt;td&gt;Commission&lt;/td&gt;&lt;td&gt;c6&lt;/td&gt;&lt;td&gt;Change (Real-time)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;c8&lt;/td&gt;&lt;td&gt;After Hours Change (Real-time)&lt;/td&gt;&lt;td&gt;d&lt;/td&gt;&lt;td&gt;Dividend/Share&lt;/td&gt;&lt;td&gt;d1&lt;/td&gt;&lt;td&gt;Last Trade Date&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;d2&lt;/td&gt;&lt;td&gt;Trade Date&lt;/td&gt;&lt;td&gt;e&lt;/td&gt;&lt;td&gt;Earnings/Share&lt;/td&gt;&lt;td&gt;e1&lt;/td&gt;&lt;td&gt;Error Indication (returned for symbol changed / invalid)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;e7&lt;/td&gt;&lt;td&gt;EPS Estimate Current Year&lt;/td&gt;&lt;td&gt;e8&lt;/td&gt;&lt;td&gt;EPS Estimate Next Year&lt;/td&gt;&lt;td&gt;e9&lt;/td&gt;&lt;td&gt;EPS Estimate Next Quarter&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;f6&lt;/td&gt;&lt;td&gt;Float Shares&lt;/td&gt;&lt;td&gt;g&lt;/td&gt;&lt;td&gt;Day's Low&lt;/td&gt;&lt;td&gt;h&lt;/td&gt;&lt;td&gt;Day's High&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;j&lt;/td&gt;&lt;td&gt;52-week Low&lt;/td&gt;&lt;td&gt;k&lt;/td&gt;&lt;td&gt;52-week High &lt;/td&gt;&lt;td&gt;g1&lt;/td&gt;&lt;td&gt;Holdings Gain Percent&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;g3&lt;/td&gt;&lt;td&gt;Annualized Gain&lt;/td&gt;&lt;td&gt;g4&lt;/td&gt;&lt;td&gt;Holdings Gain&lt;/td&gt;&lt;td&gt;g5&lt;/td&gt;&lt;td&gt;Holdings Gain Percent (Real-time)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;g6&lt;/td&gt;&lt;td&gt;Holdings Gain (Real-time)&lt;/td&gt;&lt;td&gt;i&lt;/td&gt;&lt;td&gt;More Info&lt;/td&gt;&lt;td&gt;i5&lt;/td&gt;&lt;td&gt;Order Book (Real-time)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;j1&lt;/td&gt;&lt;td&gt;Market Capitalization&lt;/td&gt;&lt;td&gt;j3&lt;/td&gt;&lt;td&gt;Market Cap (Real-time)&lt;/td&gt;&lt;td&gt;j4&lt;/td&gt;&lt;td&gt;EBITDA&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;j5&lt;/td&gt;&lt;td&gt;Change From 52-week Low&lt;/td&gt;&lt;td&gt;j6&lt;/td&gt;&lt;td&gt;Percent Change From 52-week Low&lt;/td&gt;&lt;td&gt;k1&lt;/td&gt;&lt;td&gt;Last Trade (Real-time) With Time&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;k2&lt;/td&gt;&lt;td&gt;Change Percent (Real-time)&lt;/td&gt;&lt;td&gt;k3&lt;/td&gt;&lt;td&gt;Last Trade Size&lt;/td&gt;&lt;td&gt;k4&lt;/td&gt;&lt;td&gt;Change From 52-week High&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;k5&lt;/td&gt;&lt;td&gt;Percent Change From 52-week High&lt;/td&gt;&lt;td&gt;l&lt;/td&gt;&lt;td&gt;Last Trade (With Time)&lt;/td&gt;&lt;td&gt;l1&lt;/td&gt;&lt;td&gt;Last Trade (Price Only)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;l2&lt;/td&gt;&lt;td&gt;High Limit&lt;/td&gt;&lt;td&gt;l3&lt;/td&gt;&lt;td&gt;Low Limit&lt;/td&gt;&lt;td&gt;m&lt;/td&gt;&lt;td&gt;Day's Range&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;m2&lt;/td&gt;&lt;td&gt;Day's Range (Real-time)&lt;/td&gt;&lt;td&gt;m3&lt;/td&gt;&lt;td&gt;50-day Moving Average&lt;/td&gt;&lt;td&gt;m4&lt;/td&gt;&lt;td&gt;200-day Moving Average&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;m5&lt;/td&gt;&lt;td&gt;Change From 200-day Moving Average &lt;/td&gt;&lt;td&gt;m6&lt;/td&gt;&lt;td&gt;Percent Change From 200-day Moving Average&lt;/td&gt;&lt;td&gt;m7&lt;/td&gt;&lt;td&gt;Change From 50-day Moving Average&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;m8&lt;/td&gt;&lt;td&gt;Percent Change From 50-day Moving Average&lt;/td&gt;&lt;td&gt;n&lt;/td&gt;&lt;td&gt;Name&lt;/td&gt;&lt;td&gt;n4&lt;/td&gt;&lt;td&gt;Notes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;o&lt;/td&gt;&lt;td&gt;Open &lt;/td&gt;&lt;td&gt;p&lt;/td&gt;&lt;td&gt;Previous Close&lt;/td&gt;&lt;td&gt;p1&lt;/td&gt;&lt;td&gt;Price Paid&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;p2&lt;/td&gt;&lt;td&gt;Change in Percent&lt;/td&gt;&lt;td&gt;p5&lt;/td&gt;&lt;td&gt;Price/Sales&lt;/td&gt;&lt;td&gt;p6&lt;/td&gt;&lt;td&gt;Price/Book&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;q&lt;/td&gt;&lt;td&gt;Ex-Dividend Date&lt;/td&gt;&lt;td&gt;r&lt;/td&gt;&lt;td&gt;P/E Ratio&lt;/td&gt;&lt;td&gt;r1&lt;/td&gt;&lt;td&gt;Dividend Pay Date&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;r2&lt;/td&gt;&lt;td&gt;P/E Ratio (Real-time)&lt;/td&gt;&lt;td&gt;r5&lt;/td&gt;&lt;td&gt;PEG Ratio&lt;/td&gt;&lt;td&gt;r6&lt;/td&gt;&lt;td&gt;Price/EPS Estimate Current Year&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;r7&lt;/td&gt;&lt;td&gt;Price/EPS Estimate Next Year&lt;/td&gt;&lt;td&gt;s&lt;/td&gt;&lt;td&gt;Symbol&lt;/td&gt;&lt;td&gt;s1&lt;/td&gt;&lt;td&gt;Shares Owned&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;s7&lt;/td&gt;&lt;td&gt;Short Ratio&lt;/td&gt;&lt;td&gt;t1&lt;/td&gt;&lt;td&gt;Last Trade Time&lt;/td&gt;&lt;td&gt;t6&lt;/td&gt;&lt;td&gt;Trade Links&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;t7&lt;/td&gt;&lt;td&gt;Ticker Trend&lt;/td&gt;&lt;td&gt;t8&lt;/td&gt;&lt;td&gt;1 yr Target Price&lt;/td&gt;&lt;td&gt;v&lt;/td&gt;&lt;td&gt;Volume&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;v1&lt;/td&gt;&lt;td&gt;Holdings Value&lt;/td&gt;&lt;td&gt;v7&lt;/td&gt;&lt;td&gt;Holdings Value (Real-time)&lt;/td&gt;&lt;td&gt;w&lt;/td&gt;&lt;td&gt;52-week Range&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;w1&lt;/td&gt;&lt;td&gt;Day's Value Change&lt;/td&gt;&lt;td&gt;w4&lt;/td&gt;&lt;td&gt;Day's Value Change (Real-time)&lt;/td&gt;&lt;td&gt;x&lt;/td&gt;&lt;td&gt;Stock Exchange&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;y &lt;/td&gt;&lt;td&gt;Dividend Yield&lt;/td&gt;&lt;td&gt;&lt;br /&gt;&lt;/td&gt;&lt;td&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt; &lt;/table&gt;&lt;br /&gt;The only web site giving this information (as far as I searched it) is &lt;a href="http://www.gummy-stuff.org/Yahoo-data.htm"&gt;http://www.gummy-stuff.org/Yahoo-data.htm&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;It e querystring parameter (e for extension?) looks like being optional (e=.csv).&lt;br /&gt;&lt;br /&gt;We will see later in this article how to retrieve quotation data from a VB.Net Application (ASP.Net or Windows Application). As said before, you can't declare the quotation place when you call the web service. In fact, the stock code contains this information. For General electric (GE), this is not obvious, but if you take a stock on the french market, L'Oreal for example, its code will be OR.PA where PA means Paris. Some companies can be quoted on several stock exchange, and each quotation is different. For example, let's take Microsoft shares : on XETRA Stock Exchange (Germany), its code is MSF.DE, the quotation is in Euro, and on NASDAQ, the code is MSFT ans the quotation in Dollars. Of course, to make things more difficult, codes are not standardized ! So you should pay the highest attention in choosing the Stock Symbol to use in the quotation web service. Unfortunately, Yahoo doesn't provide any web service for symbol lookup.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;em&gt;&lt;strong&gt;Indices components Web Service&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;This is probably the simplest web service provided, but it can be very helpful. It's goal is to provide a list of all stocks composing an indice : Dow Jones Industrial, Nasdaq 100, CAC40... These indices quotations are calculated as an average of its components quotation. This web service maintains the list of components (a huge work in itself) and their quotation.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;Its call is very similar to the regular quotation service, as if you were adding all stock symbols in the querystring. This is web page of the service : &lt;a href="http://finance.yahoo.com/q/cp?s=%5ENDX"&gt;http://finance.yahoo.com/q/cp?s=%5ENDX&lt;/a&gt; for Nasdaq 100 components which symbol is ^NDX. To download the information, we call &lt;a href="http://finance.yahoo.com/d/quotes.csv?s=@%5ENDX&amp;amp;f=sl1d1t1c1ohgv&amp;e=.csv"&gt;http://finance.yahoo.com/d/quotes.csv?s=@%5ENDX&amp;amp;f=sl1d1t1c1ohgv&amp;e=.csv&lt;/a&gt; where we recognize the parameters of the quotation web service. The result is a csv stream that can be considered as a web service and looks like :&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;AAPL,37.31,"6/28/2005","4:00pm",+0.21,37.49,37.59,37.17,12555196&lt;br /&gt;ADBE,28.70,"6/28/2005","4:00pm",-0.14,29.05,29.05,28.25,7916337&lt;br /&gt;ADSK,34.81,"6/28/2005","4:00pm",+0.86,34.00,34.92,33.49,2695397&lt;br /&gt;ALTR,19.52,"6/28/2005","4:00pm",-0.19,20.00,20.00,19.41,9181970&lt;br /&gt;AMAT,16.31,"6/28/2005","4:00pm",+0.08,16.36,16.42,16.24,16429051&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;However, this web service has a strange behavior depending on the URL called. For American indices, you have to deal with pagination : you can only get 50 stocks in your file. So, to download all data for Nasdaq 100, you have to call the service 6twice (there are 100 stocks composing the indice !). This is highly inefficient but understandable as a provider point of view. But what strikes me, is that it is not the same policy on other countries stock markets ! Considering French Yahoo, if you download the information from &lt;a href="http://fr.old.finance.yahoo.com/d/quotes.csv?s=@%5ENDX&amp;amp;f=snl1d1t1c1ohgv&amp;e=.csv"&gt;http://fr.old.finance.yahoo.com/d/quotes.csv?s=@^NDX&amp;amp;f=snl1d1t1c1ohgv&amp;e=.csv&lt;/a&gt; , you will get the whole information with a single call !!!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;em&gt;&lt;strong&gt;Historical data Web Service&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;A list of historical quotations (and dividend payment) is available through a web service. This web service takes as parameters 2 dates , a stock symbol and a frequency (daily, weekly, monthlyor dividend only). In the case of weekly and monthly frequency, an average on each period is done. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;At this URl , &lt;a href="http://finance.yahoo.com/q/hp?s=GE&amp;amp;a=00&amp;b=1&amp;amp;c=2004&amp;d=05&amp;amp;e=28&amp;f=2005&amp;amp;g=d"&gt;http://finance.yahoo.com/q/hp?s=GE&amp;a=00&amp;amp;b=1&amp;c=2004&amp;amp;d=05&amp;e=28&amp;amp;f=2005&amp;g=d&lt;/a&gt;, a list of daily quotations for General Electric is given from january 1st 2004 to june 28th 2005. The parameters are almost strightforward :&lt;br /&gt;&lt;br /&gt;a : first date month (0-based array : january =0, february = 1,... december =11)&lt;br /&gt;b : first date day&lt;br /&gt;c : fist date year&lt;br /&gt;d : last date month (0-based array : january =0, february = 1,... december =11)&lt;br /&gt;e : last date day&lt;br /&gt;f : last date year&lt;br /&gt;g : frequency (d = daily, w = weekly, m = monthly, v = dividends only)&lt;br /&gt;&lt;br /&gt;The URL to call as a web service is &lt;a href="http://ichart.finance.yahoo.com/table.csv?s=GE&amp;amp;a=00&amp;b=1&amp;amp;c=2004&amp;d=05&amp;amp;e=28&amp;f=2005&amp;amp;g=d&amp;ignore=.csv"&gt;http://ichart.finance.yahoo.com/table.csv?s=GE&amp;amp;a=00&amp;b=1&amp;amp;c=2004&amp;d=05&amp;amp;e=28&amp;f=2005&amp;amp;g=d&amp;amp;ignore=.csv&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;No pagination problem here, the result is a table with the first row describing the columns :&lt;br /&gt;&lt;br /&gt;Date,Open,High,Low,Close,Volume,Adj. Close*&lt;br /&gt;27-Jun-05,34.72,34.86,34.59,34.61,23402900,34.61&lt;br /&gt;24-Jun-05,34.75,35.98,34.15,34.78,67540496,34.78&lt;br /&gt;23-Jun-05,35.50,35.63,34.52,34.66,48926900,34.66&lt;br /&gt;22-Jun-05,36.20,36.34,35.68,35.72,29200400,35.50&lt;br /&gt;&lt;br /&gt;Brightly, Yahoo guys provides us with the Adjusted Close which takes into consideration dividends payment and stock splits.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8091209-111989401017101325?l=ittech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ittech.blogspot.com/feeds/111989401017101325/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8091209&amp;postID=111989401017101325' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8091209/posts/default/111989401017101325'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8091209/posts/default/111989401017101325'/><link rel='alternate' type='text/html' href='http://ittech.blogspot.com/2005/06/in-depth-examination-of-yahoo.html' title='An in-depth examination of Yahoo! Financial Web Services'/><author><name>Bertrand</name><uri>http://www.blogger.com/profile/11449343555146205550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bpujos.free.fr/bp_small.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8091209.post-111117327910278857</id><published>2005-05-31T20:07:00.000+02:00</published><updated>2005-06-13T08:43:49.350+02:00</updated><title type='text'>Passing ID with querystring made secure</title><content type='html'>&lt;span style="font-size:85%;"&gt;Sometimes you would love to pass some parameters as querystring to your web page : for example, you want to send an email with a link to a specific page with parameters, or you want to make sure that your page can be added to the Favorites.&lt;br /&gt;But security concerns will refrain from using this simple technic...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;em&gt;&lt;strong&gt;Do you really want to reveal your secrets ?&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;br&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;The main reason to avoid passing parameters as querystring is that your web site users will be able to guess other parameters value based on what they see. The worst example would be to make a database user id visible in the URL. Changing the URL, and setting a new id would probably allow to impersonate another user... Of course there are many ways to check the user id in the destination web page, but wouldn't it be nice to refrain the "I-have-always-dreamed-of-being-a-hacker" temptation ?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Don't feel either to confident in passing parameters as POST : if you really want to sniff the communication with the server, you will find the information as clear text.&lt;/span&gt;&lt;br&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;em&gt;&lt;strong&gt;The only solution : Encryption !&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;br&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Using encryption, it will be almost impossible for the user to "understand" the &lt;strong&gt;crypted&lt;/strong&gt; text passed as parameters, but you (and only you) will still be able to &lt;strong&gt;decrypt&lt;/strong&gt; it and retrieve the correct parameter. W&lt;/span&gt;&lt;span style="font-size:85%;"&gt;e would like to translate http://www.selvatech.com/user_id=194 into http://www.selvatech.com/user_id=AZRZERVBFVF945FFERF566T3 (anyone will admit that guessing another user id based on AZRZERVBFVF945FFERF566T3 is harder than on 194!). Isn't it what we want ?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Let's take a second to talk about cryptology, and more precisely .Net cryptology. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;All native .Net cryptology classes are in the System.Security.Cryptography namespace.&lt;br /&gt;Many articles deal will the security aspect in .Net, so I will make it short and give you the link to the best articles at the end of this post.&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;There are various available methods in the .Net Framework to encrypt piece of plain text, the most famous are Rijndael (RijndaelManaged) , DES (DESCryptoServiceProvider), Triple Des (TripleDESCryptoServiceProvider), RC2 (RC2CryptoServiceProvider). All this classes have some caracteristics in common :&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;- They use a key with a determined length (expressed in bits) to encrypt and decrypt a piece of text,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;- They can use an Initial Vector (IV) , different Padding modes, Cipher modes and Block Size,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;- The Array of Bytes is the best type to use within the encryption classes.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;In this post, we will only deal with symmetric encryption which uses a secret key value to encrypt and decrypt the data. Both the sender and receiver need the same key in order to encrypt or decrypt. In our case the program which sends the email containing the link, and the destination web page must access the secret key, and use exactly the same parameters for encryption and decryption.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;After reading &lt;a href="http://www.dotnetdevs.com/articles/UsingEncryption.aspx" target="_blank"&gt;Using encryption in .Net&lt;/a&gt; by Steve Johnson, I think it's good to rewrite the principles exposed in his conclusion : &lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Always use proven, public technology&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Use Rijndael, if possible&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Use 256-bit keys and blocks&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Take care how you derive keys&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Use PKCS7 padding in .NET 1.1, ISO10126 in .NET 2.0&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Don't use ECB mode unless you have a good reason and know what you're doing&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Always use a unique IV for each message&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Take the time to be explicit in your code for important details, even when you're using defaults&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;In the rest of this post, I will try to put in practice Steve principles (except the "Always use a unique IV for each message" which I think is not adapted to symmetric encryption because both the sender and the receiver must know the Initial Vector).&lt;/span&gt;&lt;br&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;em&gt;&lt;strong&gt;Now let's see some VB.Net coding in action !&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;br&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;The first problem we have to solve is : how do I generate a 256-bits key ?&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;This is a very good question ! 256 bits means 32 bytes (1 byte = 8 bits) to provide to the encryption algorithm. As the key is all you need to know to "understand" your secrets (well you need to know the encryption method, the IV used, the padding too ...), it's a good practice to think twice before choosing.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;We could try to use a "simple password" like one of my favorite : iloveselvatech and generate a 256-bits key from it. How can we do this ? &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;So simply : we only need to use some &lt;strong&gt;hashing methods&lt;/strong&gt; included in the .Net Framework. Hashing is the transformation of a string of characters into a fixed-length value or key that represents the original string. In other words a hash is like a fingertip : it identifies uniquely the string from which it has been generated. Different hashing algorithms exist in .Net : the most famous are MD5 and SHA. MD5 produces 128-bits hash, whereas SHA can produce 160, 256, 384 and 512-bits hash. The good point in using hashing with encryption in .Net is that both use array of bytes as native type.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;In our example, we can use a SHA256 hash from our iloveselvatech password. This is our simple hash-SHA256 class (the whole thing is in the ComputeHash method) :&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;Public Class hash_SHA256&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Private&lt;/span&gt; _dhashSHA256 &lt;span style="color: rgb(51, 51, 255);"&gt;As&lt;/span&gt; System.Security.Cryptography.SHA256Managed&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Public Sub New&lt;/span&gt;()&lt;br /&gt;_dhashSHA256 = &lt;span style="color: rgb(51, 51, 255);"&gt;New&lt;/span&gt; System.Security.Cryptography.SHA256Managed&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;End Sub&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Public Function&lt;/span&gt; ComputeHash(&lt;span style="color: rgb(51, 51, 255);"&gt;ByVal&lt;/span&gt; data &lt;span style="color: rgb(51, 51, 255);"&gt;As String&lt;/span&gt;) &lt;span style="color: rgb(51, 51, 255);"&gt;As Byte&lt;/span&gt;()&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Return&lt;/span&gt; _dhashSHA256.ComputeHash(string2array(data))&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;End Function&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Public Function&lt;/span&gt; string2array(&lt;span style="color: rgb(51, 51, 255);"&gt;ByVal&lt;/span&gt; data &lt;span style="color: rgb(51, 51, 255);"&gt;As String&lt;/span&gt;) &lt;span style="color: rgb(51, 51, 255);"&gt;As Byte&lt;/span&gt;()&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Return&lt;/span&gt; System.Text.Encoding.&lt;span style="color: rgb(51, 51, 255);"&gt;Default&lt;/span&gt;.GetBytes(data)&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;End Function&lt;/span&gt; &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Public Function&lt;/span&gt; array2string(&lt;span style="color: rgb(51, 51, 255);"&gt;ByVal&lt;/span&gt; data &lt;span style="color: rgb(51, 51, 255);"&gt;As Byte&lt;/span&gt;()) &lt;span style="color: rgb(51, 51, 255);"&gt;As string&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Return &lt;/span&gt;System.Text.Encoding.&lt;span style="color: rgb(51, 51, 255);"&gt;Default&lt;/span&gt;.GetString(data)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;End Function&lt;/span&gt; &lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;End Class&lt;/span&gt;&lt;/p&gt;&lt;span style="color: rgb(51, 51, 255);font-family:Courier New;font-size:85%;"  &gt;&lt;/span&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;Then, we will generate our 256-bits length message :&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Private Function&lt;/span&gt; Generate256bitskey (&lt;span style="color: rgb(51, 51, 255);"&gt;byval&lt;/span&gt; str &lt;span style="color: rgb(51, 51, 255);"&gt;as string&lt;/span&gt;) &lt;span style="color: rgb(51, 51, 255);"&gt;as byte&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(51, 51, 255);"&gt;dim&lt;/span&gt; hashclass &lt;span style="color: rgb(51, 51, 255);"&gt;As&lt;/span&gt; hash_SHA256&lt;br /&gt;hashclass = &lt;span style="color: rgb(51, 51, 255);"&gt;New&lt;/span&gt; hash_SHA256&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;return&lt;/span&gt; hashclass.ComputeHash(str)&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(51, 51, 255);"&gt;End Function&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;In our case, a SHA256 hash of iloveselvatech will be : {246 , 70 , 154 , 164 , 75 , 50 , 110 , 43 , 92 , 82 , 207 , 70 , 192 , 125 , 121 , 100 , 102 , 222 , 109 , 9 , 192 , 236 , 14 , 131 , 139 , 146 , 110 , 243 , 65 , 126 , 149 , 192} as an array of bytes.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;But, even if you can find this key difficult to read, it's easy to break if you guess that you are using a SHA256 algorithm. Using a brute force strategy, it is relatively easy (but time consuming) to find the original 14 letters code which produce this unreadable key.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;Another technic, and better approach, is to generate your own 256-bits key. This is the same approach I will use for generating the Initial Vector later. Here is my code :&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Private Function&lt;/span&gt; Generate256bitsKey() &lt;span style="color: rgb(51, 51, 255);"&gt;As Byte&lt;/span&gt;()&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Dim&lt;/span&gt; table() &lt;span style="color: rgb(51, 51, 255);"&gt;As Byte&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Dim&lt;/span&gt; str &lt;span style="color: rgb(51, 51, 255);"&gt;As String&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;dim&lt;/span&gt; i &lt;span style="color: rgb(51, 51, 255);"&gt;as integer&lt;/span&gt;&lt;br /&gt;str="WWW.SELVATECH.COM"&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;For&lt;/span&gt; i=1 &lt;span style="color: rgb(51, 51, 255);"&gt;To&lt;/span&gt; 100&lt;br /&gt;str = str &amp; &lt;span style="color: rgb(51, 51, 255);"&gt;Chr&lt;/span&gt;(3 * i &lt;span style="color: rgb(51, 51, 255);"&gt;Mod&lt;/span&gt; 255)&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Next&lt;/span&gt;&lt;br /&gt;table=System.Text.Encoding.&lt;span style="color: rgb(51, 51, 255);"&gt;Default&lt;/span&gt;.GetBytes(str)&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Dim&lt;/span&gt; tabiv(32) &lt;span style="color: rgb(51, 51, 255);"&gt;As Byte&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Array&lt;/span&gt;.Copy(table, tabiv, 31)&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;return&lt;/span&gt; tabiv&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;End Function&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;In this case, I generate a long string with a determined, but difficult to find algorithm, that I convert into a 32-bytes long array of byte (remember that 32-bytes means 256 bits...)&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;How do I build my encrypting class ?&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;We choosed to use a Rijndael 256-bits key and blocks algorithm, using PKCS7 padding and not ECB cipher mode. I won't go into details with these specifications, that's what MSDN is here for ! Happily, .Net classes are smart enough, to instanciate easily our object :&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Public Class&lt;/span&gt; crypto_Rijndael&lt;/span&gt;&lt;/p&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&lt;p&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Private&lt;/span&gt; _rijndael &lt;span style="color: rgb(51, 51, 255);"&gt;As&lt;/span&gt; System.Security.Cryptography.RijndaelManaged&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Public Sub New&lt;/span&gt;()&lt;br /&gt;_rijndael = New System.Security.Cryptography.RijndaelManaged&lt;br /&gt;_rijndael.Mode = System.Security.Cryptography.CipherMode.CBC&lt;br /&gt;_rijndael.Padding= System.Security.Cryptography.PaddingMode.PKCS7&lt;br /&gt;_rijndael.BlockSize=256&lt;br /&gt;_rijndael.KeySize=256&lt;br /&gt;_rijndael.IV=GenerateIV()&lt;br /&gt;_rijndael.Key=GenerateCryptoKey()&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;End Sub&lt;/span&gt;&lt;/p&gt;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: rgb(51, 51, 255);font-family:Courier New;font-size:85%;"  &gt;End Class&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;Where GenerateIV() and GenerateCryptoKey() produce 32-bytes-length array as seens above.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;Then we need 2 methods : Encrypt and Decrypt.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Public Function&lt;/span&gt; Encrypt(&lt;span style="color: rgb(51, 51, 255);"&gt;ByVal&lt;/span&gt; data &lt;span style="color: rgb(51, 51, 255);"&gt;As String&lt;/span&gt;) &lt;span style="color: rgb(51, 51, 255);"&gt;As Byte&lt;/span&gt;()&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Dim&lt;/span&gt; rijEncrypt &lt;span style="color: rgb(51, 51, 255);"&gt;As&lt;/span&gt; System.Security.Cryptography.ICryptoTransform = _rijndael.CreateEncryptor()&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Dim&lt;/span&gt; buff() &lt;span style="color: rgb(51, 51, 255);"&gt;As Byte&lt;/span&gt; = string2array(data)&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Return&lt;/span&gt; rijEncrypt.TransformFinalBlock(buff, 0, buff.Length)&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;End Function&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Public Function&lt;/span&gt; Decrypt(ByVal sEncryptedData As String) As Byte()&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Dim&lt;/span&gt; rijEncrypt &lt;span style="color: rgb(51, 51, 255);"&gt;As&lt;/span&gt; System.Security.Cryptography.ICryptoTransform = _rijndael.CreateDecryptor()&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Dim&lt;/span&gt; buff() &lt;span style="color: rgb(51, 51, 255);"&gt;As Byte&lt;/span&gt; = Convert.FromBase64String(sEncryptedData)&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Return&lt;/span&gt; rijEncrypt.TransformFinalBlock(buff, 0, buff.Length)&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;End Function&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;As you can see, these methods are very simple, however, there is an important point we have to speak about : &lt;strong&gt;encoding&lt;/strong&gt;. This point will make clear the use of Convert.FromBase64String in the Decrypt method.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;What is the problem with encoding ?&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:85%;"&gt;We want to cipher a string into another string that can be used in a querystring. This point should help us to focus on &lt;strong&gt;Base64&lt;/strong&gt; and &lt;strong&gt;HEX&lt;/strong&gt; formats. &lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;An HEX-formated text will look like : 414F664141644D383962336874425933714 whereas Base64-formated text will look like : AOfAAdM89b3htBY3qAehu5omm0QvLXLrr0YHo/tUAfo=.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Base64 encoding format is about 33% more efficient than HEX encoding, however, passing Base64-encoded information withtin the URL can generate problem because of URLencoding mechanism, for example, + in the URL is re-encoded as ' '. This problem doesn't exist with HEX-encoding.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;We will first transform the array of bytes which is returned by the Encrypt method as a Base64-string, and we will translate this string into a HEX-formated string before writing it to the querystring (there is no simple way to convert an array of byte into a HEX-string).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Our method for writing the querysting will be :&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;url = string_TO_hexa(Convert.ToBase64String(crypto_Rijndael.Encrypt(encryptedtext)))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;with&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Private Function&lt;/span&gt; string_TO_hexa(&lt;span style="color: rgb(51, 51, 255);"&gt;ByVal&lt;/span&gt; data &lt;span style="color: rgb(51, 51, 255);"&gt;As String&lt;/span&gt;) &lt;span style="color: rgb(51, 51, 255);"&gt;As String&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Dim&lt;/span&gt; i &lt;span style="color: rgb(51, 51, 255);"&gt;As Integer&lt;/span&gt;&lt;br /&gt;string_TO_hexa = ""&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;For&lt;/span&gt; i = 1 &lt;span style="color: rgb(51, 51, 255);"&gt;To&lt;/span&gt; &lt;span style="color: rgb(51, 51, 255);"&gt;Len&lt;/span&gt;(data)&lt;br /&gt;string_TO_hexa = string_TO_hexa &amp; Strings.&lt;span style="color: rgb(51, 51, 255);"&gt;Right&lt;/span&gt;("0" + &lt;span style="color: rgb(51, 51, 255);"&gt;Hex&lt;/span&gt;(&lt;span style="color: rgb(51, 51, 255);"&gt;Asc&lt;/span&gt;(&lt;span style="color: rgb(51, 51, 255);"&gt;Mid&lt;/span&gt;(data, i, 1))), 2)&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Next&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;End Function&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style="font-size:85%;"&gt;Then, at the destination page, we get the querystring parameter HEX-encoded. &lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;secrettext = array2string(crypto_Rijndael.Decrypt(hexa_TO_string(querystring)))&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;with &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Public Function&lt;/span&gt; hexa_TO_string(&lt;span style="color: rgb(51, 51, 255);"&gt;ByVal&lt;/span&gt; data &lt;span style="color: rgb(51, 51, 255);"&gt;As String&lt;/span&gt;) &lt;span style="color: rgb(51, 51, 255);"&gt;As String&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Dim&lt;/span&gt; i &lt;span style="color: rgb(51, 51, 255);"&gt;As Integer&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;For&lt;/span&gt; i = 1 &lt;span style="color: rgb(51, 51, 255);"&gt;To Len&lt;/span&gt;(data) &lt;span style="color: rgb(51, 51, 255);"&gt;Step&lt;/span&gt; 2&lt;br /&gt;hexa_TO_string = hexa_TO_string &amp; &lt;span style="color: rgb(51, 51, 255);"&gt;Chr&lt;/span&gt;(&lt;span style="color: rgb(51, 51, 255);"&gt;CType&lt;/span&gt;("&amp;amp;amp;amp;amp;amp;amp;H" &amp; &lt;span style="color: rgb(51, 51, 255);"&gt;Mid&lt;/span&gt;(data, i, 2), &lt;span style="color: rgb(51, 51, 255);"&gt;Integer&lt;/span&gt;))&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Next&lt;br /&gt;End Function&lt;/span&gt;&lt;/span&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt; &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;With the function above, we translate the HEX-formated text back into a Base64-string. And during the Decrypt process, we use :&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=";font-family:Courier New;font-size:85%;"  &gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Dim&lt;/span&gt; buff() &lt;span style="color: rgb(51, 51, 255);"&gt;As Byte&lt;/span&gt; = Convert.FromBase64String(sEncryptedData)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;which translates a Base64-string into an array of Bytes.&lt;/span&gt;&lt;br&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;em&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;br&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;First of all, I spent a long time fighting with Cipher.Mode when I built my instances of Rijndael, the reason is if you don't pick up ECB mode (less secure, cf articles), don't forget to initialise the IV property of the&lt;br /&gt;RijndaelManaged class (otherwise, it will generate each time you instanciate the class a random new IV, and in this case, you won't be able to decrypt your text).&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;The .Net classes related to Cryptography (at least for the symmetric encryption) are very user friendly so there's no point of not using them !&lt;/span&gt; &lt;/p&gt;&lt;span style="font-size:85%;"&gt;Some interesting articles about cryptology and .Net:&lt;/span&gt;&lt;br /&gt;&lt;a title="http://www.garykessler.net/library/crypto.html" href="http://www.garykessler.net/library/crypto.html" target="_blank"&gt;&lt;span style="font-size:78%;"&gt;An Overview of Cryptography&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:78%;"&gt; : long article about cryptology in general&lt;br /&gt;&lt;/span&gt;&lt;a title="http://www.developer.com/net/net/article.php/1548761" href="http://www.developer.com/net/net/article.php/1548761" target="_blank"&gt;&lt;span style="font-size:78%;"&gt;Cryptography in .NET&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:78%;"&gt; : the use of private and public keys in .Net&lt;br /&gt;&lt;/span&gt;&lt;a title="http://www.4guysfromrolla.com/webtech/090501-1.shtml" href="http://www.4guysfromrolla.com/webtech/090501-1.shtml" target="_blank"&gt;&lt;span style="font-size:78%;"&gt;Using Symmetric Cryptography in an ASP.NET Web Page&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:78%;"&gt; : using cryptology in an ASP.Net web page&lt;br /&gt;&lt;/span&gt;&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/cryptosimplified.asp" target="_blank"&gt;&lt;span style="font-size:78%;"&gt;Cryptography Simplified in Microsoft .NET&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:78%;"&gt; : Microsoft article about basic cryptology (hashing, keys...) with .Net&lt;br /&gt;&lt;/span&gt;&lt;a title="http://www.devx.com/security/Article/7019/0/page/1" href="http://www.devx.com/security/Article/7019/0/page/1" target="_blank"&gt;&lt;span style="font-size:78%;"&gt;Keeping Secrets: A Guide to VB .NET Cryptography&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:78%;"&gt; : A guide for private key generation using vectors&lt;br /&gt;&lt;/span&gt;&lt;a href="http://www.devcity.net/Articles/47/1/encrypt_querystring.aspx" target="_blank"&gt;&lt;span style="font-size:78%;"&gt;Encrypting QueryStrings with .NET&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:78%;"&gt; : Exactly what we want to do, but if the article is good, I've found some formating problems in the code&lt;br /&gt;&lt;/span&gt;&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/bdadotnetarch15.asp" target="_blank"&gt;&lt;span style="font-size:78%;"&gt;Performance Comparison: Security Design Choices&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:78%;"&gt; : Compare hashing and encrypting techniques performances&lt;br /&gt;&lt;/span&gt;&lt;a href="http://www.developerfusion.com/show/4647/1" target="_blank"&gt;&lt;span style="font-size:78%;"&gt;Using Encryption in .NET&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:78%;"&gt; : Excellent article on .Net encryption (keys, encryption algorithm, detailled study of Rijndael Provider) &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8091209-111117327910278857?l=ittech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ittech.blogspot.com/feeds/111117327910278857/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8091209&amp;postID=111117327910278857' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8091209/posts/default/111117327910278857'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8091209/posts/default/111117327910278857'/><link rel='alternate' type='text/html' href='http://ittech.blogspot.com/2005/05/passing-id-with-querystring-made.html' title='Passing ID with querystring made secure'/><author><name>Bertrand</name><uri>http://www.blogger.com/profile/11449343555146205550</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bpujos.free.fr/bp_small.jpg'/></author><thr:total>0</thr:total></entry></feed>
