Can the DecodeSCKey and DecodeD2Key functions be used as a key validator?
Quote from: BlazingKnight on October 09, 2003, 12:21 PM
Can the DecodeSCKey and DecodeD2Key functions be used as a key validator?
If you mean the YobGuls versions, they provide the same kind of protection as the game installers - protection against making a typo in the key. Just because a key passes the installer check, though, does not mean that it will be accepted by the Battle.net server.
I'll take that as a yes. Ok, the next thing. I have a program running keys through the key decoder. There's an input list (original list), and an output list (processed through decoder). In the output list, the keys all come out different. How do I tell if it is valid or not. (True/False value).
You don't need to call decodecdkey. That'll do a whole bunch of stuff you don't need. Decoding a CD key has 3 main sections, the first is the one you're interested in - the checksum. It works by computing a value based on the characters in the key. If that character matches the last key character, the key is considered valid for an install. Otherwise, it's not. Here's my code for computing the checksum. This is reversed from battle.snp, so it won't work for Diablo II. I don't think I ever reversed that but Yobguls version should work fine if you can figure out which part it is :)
// Checksum
DWORD Checksum = 3;
for(int i = 0; i < 12; i++){
Checksum += (Key[i] - 0x30) ^ (Checksum * 2);
}
Checksum %= 10;
if(Key[12] != Checksum + 0x30){
return false;
}
The rest of the decoding gets the key's values to send to Battle.net, but since we don't know how to validate those, there's not much point in decoding them if you're only writing a validator.
Can you give that to me in VB please. Sorry for not mentioning the language.
Quote from: BlazingKnight on October 09, 2003, 04:07 PM
Can you give that to me in VB please. Sorry for not mentioning the language.
// Checksum
DWORD Checksum = 3;
for(int i = 0; i < 12; i++){
Checksum += (Key[i] - 0x30) ^ (Checksum * 2);
}
Checksum %= 10;
if(Key[12] != Checksum + 0x30){
return false;
}
It shoudl be something similar to this:
dim Checksum as integer
Checksum = 3
for i = 0 to 11
Checksum = val(mid(key, i, 1)) xor (Checksum * 2)
next i
Checksum = Checksum mod 10
if Checksum != mid(key, 13, 1) then
fail;
else
pass;
end if
But keep in mind there's a 1/10 chance it'll pass this for a random key...
Thanks for converting iago. Heres what I have for my code as of now.
Do
Dim i As Integer
Dim i2 As Integer
Dim Checksum As Integer
Checksum = 0
Dim Key As String
Key = lstKeys.List(i2)
For i = 0 To 11
Checksum = Val(Mid(Key, i, 1)) Xor (Checksum * 2)
Next i
Checksum = Checksum Mod 10
If Checksum <> Mid(Key, 13, 1) Then
lstInvalid.AddItem Key
Else
lstValid.AddItem Key
End If
i2 = i2 + 1
Loop Until i2 = lstKeys.ListCount
I messed w/ it, but I get an "Invalid procedure call or argument" error on the line.
Checksum = Val(Mid(Key, i, 1)) Xor (Checksum * 2)
I couldn't fix it mainly becuase I don't know what XOr and Mod mean. Please fill in the blanks for me. (Thanks)
xor is "exclusive or."
I.e. "a xor b," also expressed as "a ^ b"
a | b | a ^ b
----------------
0 | 0 | 0
0 | 1 | 1
1 | 0 | 1
1 | 1 | 0
That illustrates the usage of xor. You really SHOULD know what it is, it's rather integral to programming.
That didn't really make any sense to me. What about Mod?
mod is Modulus Division, which is like the division but it returns the remainder instead of the product.
And I probably did the "mid" backwards, I haven't used it for years.
Mid(String, Start, Stop) / Mid(strInput, 1, 4
I talked w/ Zakath in the channel. He broke it down for me some. For those who are still curious, I'll stupify it a little more for the people on my level. >.<
If you have an If/Then statement and your comparing two variables, only 1 of the variables can be true to have a true output. So...
If a = True XOr b = True then
False Output
ElseIf a = Flse XOr b = False Then
False Output
ElseIf a = True XOr b = False Then
True Output
End If
Where as a regular If/Then statement would allow you to have two true variables to have a true output. Thanks Zakath.
If you have an If/Then statement and your comparing two variables, only 1 of the variables can be true to have a true output. So...
That's an OR statement. In other words, if either condition is true, the 'output' is true. If you want to change that so that both have to be true, simply use an AND statment. I've never used XOR in a conditional check and I'm not sure what the point in that would be. Is it even possible in most languages? It's more commonly used to manipulate the bits in a byte, ie:
11 XOR 5 = 14
because:
1011 (11)
0101 (5)
1110 (XOR'd - 14)
You can think of 1 as true and 0 as false if that helps.
Quote from: iago on October 09, 2003, 05:04 PM
Quote from: BlazingKnight on October 09, 2003, 04:07 PM
Can you give that to me in VB please. Sorry for not mentioning the language.
// Checksum
DWORD Checksum = 3;
for(int i = 0; i < 12; i++){
Checksum += (Key[i] - 0x30) ^ (Checksum * 2);
}
Checksum %= 10;
if(Key[12] != Checksum + 0x30){
return false;
}
It shoudl be something similar to this:
dim Checksum as integer
Checksum = 3
for i = 0 to 11
Checksum = val(mid(key, i, 1)) xor (Checksum * 2)
next i
Checksum = Checksum mod 10
if Checksum != mid(key, 13, 1) then
fail;
else
pass;
end if
But keep in mind there's a 1/10 chance it'll pass this for a random key...
Shouldn't != be <> in VB
Yes.
Note this line:
QuoteIt should be something similar to this:
I haven't done any visual basic in a long, long time.. I was close :)
Got bored, wrote this inefficient thing to generate all "valid" keys.
#include <iostream.h>
#include <fstream.h>
#include <string.h>
#include <stdlib.h>
#define DWORD unsigned long
__inline bool Checksum(char * Key);
int main()
{
char Key[14];
char TempBuf[6]; char TempBuf2[5]; char TempBuf3[6]; char TempBuf4[5];
int TempInt;
ofstream OutFile;
OutFile.open("keys.txt");
long i; long j; long k;
for ( i = 0; i < 5000; i++ )
{
for ( j = 0; j < 100000; j++ )
{
for ( k = 0; k < 10000; k++ )
{
strcpy(TempBuf4, "0000");
strcpy(TempBuf3, "00000");
_ltoa(k, TempBuf2, 10);
TempInt = strlen(TempBuf2);
strcpy(&TempBuf4[4 - TempInt], TempBuf2);
strcpy(&Key[9], TempBuf4);
strcpy(TempBuf4, "0000");
_ltoa(i, TempBuf2, 10);
TempInt = strlen(TempBuf2);
strcpy(&TempBuf4[4 - TempInt], TempBuf2);
strcpy(&Key[0], TempBuf4);
_ltoa(j, TempBuf, 10);
TempInt = strlen(TempBuf);
strcpy(&TempBuf3[5 - TempInt], TempBuf);
strcpy(&Key[4], TempBuf3);
if ( Checksum( Key ) )
OutFile << Key << endl;
}
}
}
OutFile.close();
return 0;
}
__inline bool Checksum(char * Key)
{
DWORD dChecksum = 3;
for(int i = 0; i < 12; i++){
dChecksum += (Key[i] - 0x30) ^ (dChecksum * 2);
}
dChecksum %= 10;
if(Key[12] != dChecksum + 0x30){
return false;
}
return true;
}
Yes. It was another one of vL's pointless test's to see if the reader was versatile enough in programming to understand it. Could you please put that validator in VB please.
You might notice most of them don't particularly like VB, so most code you will get will be in C++ unless anyone feels like "translating" it.
Weeding out the morons is a good thing.
There, fully and correctly functioning VB validation code.
Public Function Checksum(ByVal CDKey As String) As Boolean
Dim TheChecksum As Long, i As Byte
TheChecksum = 3
For i = 1 To 12
TheChecksum = TheChecksum + ((Asc(Mid(CDKey, i, 1)) - &H30) Xor (TheChecksum * 2))
Next i
TheChecksum = TheChecksum Mod 10
If Asc(Mid(CDKey, 13, 1)) <> (TheChecksum + &H30) Then
Checksum = False
Exit Function
End If
Checksum = True
End Function
Thanks CupHead. I owe ya :)
Quote from: BlazingKnight on October 12, 2003, 03:45 PM
Thanks CupHead. I owe ya :)
The question becomes ... will you ever pay him?
Aim: MrTunaBreeze
Talk to me about payment.
If Asc(Mid(CDKey, 13, 1)) <> (TheChecksum + &H30) Then
-- compared to --
if(CDKey[12] - 0x30 == TheChecksum)
Who says VB is nicer? :-P