Click here to Skip to main content
Click here to Skip to main content

Microsoft Product Key Finder

By , 31 Jan 2008
 

Introduction

The Raw Product Key is buried inside the Product Key that is printed on the sticker distributed with each Windows XP CD. It consists of five alphanumeric strings separated by '-' characters, where each string is composed of five characters, as in:

FFFFF-GGGGG-HHHHH-JJJJJ-KKKKK

Each character is one of the following 24 letters and digits:

B C D F G H J K M P Q R T V W X Y 2 3 4 6 7 8 9

Very similar to the decimal encoding of the Installation ID, the 25 characters of the Product Key form a base-24 encoding of the binary representation of the Product Key. Decoding the Product Key yields a multi-precision integer of roughly 115 bits, which is stored - again in Little Endian byte order - in an array of 15 bytes. Decoding the above Product Key results in the following byte sequence:

0x6F 0xFA 0x95 0x45 0xFC 0x75 0xB5 0x52
0xBB 0xEF 0xB1 0x17 0xDA 0xCD 0x00

Of these 15 bytes, the least significant four bytes contain the Raw Product Key in Little Endian byte order. The least significant bit is removed by shifting this 32-bit value (0x4595FA6F - remember the Little Endian byte order) to the left by one bit position, resulting in a Raw Product Key of 0x22CAFD37, or 583728439 in decimal notation.

Using the code

Using this code, you can find the product key of your Microsoft products.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
namespace MSKeyFinder
{
    public class KeyDecoder
    {
        public enum Key { XP, Office10, Office11 };
        public static byte[] GetRegistryDigitalProductId(Key key)
        {
            byte[] digitalProductId = null;
            RegistryKey registry = null;
            switch (key)
            {
                // Open the XP subkey readonly.
                case Key.XP:
                    registry =
                      Registry.LocalMachine.
                        OpenSubKey(
                          @"SOFTWARE\Microsoft\Windows NT\CurrentVersion",
                            false);
                    break;
                // Open the Office 10 subkey readonly.
                case Key.Office10:
                    registry =
                      Registry.LocalMachine.
                        OpenSubKey(
                          @"SOFTWARE\Microsoft\Office\10.0\Registration\" + 
                          @"{90280409-6000-11D3-8CFE-0050048383C9}",
                          false);
                    // TODO: Open the registry key.
                    break;
                // Open the Office 11 subkey readonly.
                case Key.Office11:
                    // TODO: Open the registry key.
                    break;
            }
            if (registry != null)
            {
                // TODO: For other products, key name maybe different.
                digitalProductId = registry.GetValue("DigitalProductId")
                  as byte[];
                registry.Close();
            }
            return digitalProductId;
        }
        public static string DecodeProductKey(byte[] digitalProductId)
        {
            // Offset of first byte of encoded product key in 
            //  'DigitalProductIdxxx" REG_BINARY value. Offset = 34H.
            const int keyStartIndex = 52;
            // Offset of last byte of encoded product key in 
            //  'DigitalProductIdxxx" REG_BINARY value. Offset = 43H.
            const int keyEndIndex = keyStartIndex + 15;
            // Possible alpha-numeric characters in product key.
            char[] digits = new char[]
      {
        'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'M', 'P', 'Q', 'R', 
        'T', 'V', 'W', 'X', 'Y', '2', '3', '4', '6', '7', '8', '9',
      };
            // Length of decoded product key
            const int decodeLength = 29;
            // Length of decoded product key in byte-form.
            // Each byte represents 2 chars.
            const int decodeStringLength = 15;
            // Array of containing the decoded product key.
            char[] decodedChars = new char[decodeLength];
            // Extract byte 52 to 67 inclusive.
            ArrayList hexPid = new ArrayList();
            for (int i = keyStartIndex; i <= keyEndIndex; i++)
            {
                hexPid.Add(digitalProductId[i]);
            }
            for (int i = decodeLength - 1; i >= 0; i--)
            {
                // Every sixth char is a separator.
                if ((i + 1) % 6 == 0)
                {
                    decodedChars[i] = '-';
                }
                else
                {
                    // Do the actual decoding.
                    int digitMapIndex = 0;
                    for (int j = decodeStringLength - 1; j >= 0; j--)
                    {
                        int byteValue = (digitMapIndex << 8) | (byte)hexPid[j];
                        hexPid[j] = (byte)(byteValue / 24);
                        digitMapIndex = byteValue % 24;
                        decodedChars[i] = digits[digitMapIndex];
                    }
                }
            }
            return new string(decodedChars);
        }
    }
}

Once you realize how the product keys are encoded, a search through the Registry for the values starting with DigitalProductId indicates that many more product keys may be encoded this way.

Further information

To know more about Microsoft product keys, visit:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Member 4079427
India India
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionThis is not working in my winodows 7member@BangIndia18hrs 14mins ago 
Its giving
BBBBB-BBBBB-BBBBBB-BBBBB-BBBBBB
 
like that my product key..
QuestionAnyone knows how to decode office 2013?membermkdsoft20 Feb '13 - 5:23 
Hi,
it seems 808 its not the same in office 2013 as office 2010?
Any success with decoding the product id in office 2013 / office 15 ?
AnswerRe: Anyone knows how to decode office 2013?memberMasterOfCoders19 Mar '13 - 11:27 
Compile for x64 and .Net Framework 4
 
registry =
Registry.LocalMachine.
OpenSubKey(
@"SOFTWARE\Microsoft\Office\15.0\Registration\" +
@"{91150000-0011-0000-1000-0000000FF1CE}", false);
SuggestionLittle TipmemberTomasz Karlinski9 Jul '11 - 3:40 
 for (int j = decodeStringLength - 1; j >= 0; j--)
     {
       int byteValue = (digitMapIndex << 8) | (byte)hexPid[j];
       hexPid[j] = (byte)(byteValue / 24);
       digitMapIndex = byteValue % 24;
     }
       decodedChars[i] = digits[digitMapIndex];
 

GeneralOffice 14 And Win7 x64memberJonFrost16 May '11 - 23:19 
Just so you guys know, I had a problem where I couldn't get the product key for office 14.0 (2010) on my Win7 x64 machine.
 
Here are the steps to fix:
 
1) Correct for 64-bit OS: in stead of looking in the regular key "SOFTWARE\Microsoft\Office\14.0\Registration\{90140000-0011-0000-1000-00FF1CE}", look in "SOFTWARE\Wow6432Node\Microsoft\Office\14.0\Registration\{90140000-003D-0000-0000-0000000FF1CE}" (thats where I found mine, I'm using O2k10 H&B). You can check if the OS is 64-bit by calling Environment.Is64BitOperatingSystem (.Net4 only I think - maybe 3/3.5 too)
2) Adjust your start offset from 52 (decimal) to 328 (hex) or 808 (decimal) and make your end offset equal start offset + 15
 
This works for me in VS2010 compiled target cpu as x64 and target framework as .NET Framework 4.
 
Hope this helps others.
GeneralMy vote of 1memberPeter Ritchie23 Apr '11 - 5:01 
copy of someone else's work
GeneralRe: My vote of 1memberreeselmiller28 Jun '11 - 9:31 
This is pretty easy to figure out on your own if you're into encription. So doubtful its stolen.
GeneralRe: My vote of 1memberMember 950092130 Oct '12 - 1:21 
When the code is 1:1 (even names of variables, etc.) with only slight changes in the header, namespace name or comments, then there is no doubt it was copied Smile | :) It would at least have been fair of the poster to name the original author or to give a link to the original authors article. If you go to the link of the original C# author (given below by saberint on 16. Jul. 2009, 21:50: http://geekswithblogs.net/willemf/archive/2006/04/23/76125.aspx), you will find that the original author was fair, and gave a link to the site of the (probably original) Delphi code from which he hacked the C# code!
GeneralRe: My vote of 1memberreeselmiller230 Oct '12 - 9:25 
Ok, I agree, didn't see that link. We must be careful to give credit to our sources. Even if it was not copied from there it is obvious that its a copy from somewhere. I have seen this code many places in various forms but this is undeniable, definately a copy.
GeneralRecover product key from crashed computermemberSteven Noto7 Jun '10 - 15:44 
Thanks for your great article!
But your code won't work if you can't boot your Windows system or your computer is locked..
I would recommend Windows Key Finder boot CD - it is able to recover product key from any computer, even if your system failed or crashed!
 
More info about Windows Key Finder boot CD: http://www.windows-key-finder.com

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 31 Jan 2008
Article Copyright 2008 by Member 4079427
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid