• Welcome to Valhalla Legends Archive.
 

Help with math problem please!

Started by Ringo, January 23, 2006, 05:21 AM

Previous topic - Next topic

Ringo

hmm, how do i say this.. i suck at math  :-\
So, what i need to do is calculate 2 numbers through a formula from 2 seed numbers, but the problem is getting the 2 seed values back!
The seed numbers can be anything from 0 to 23.
Example:

    Dim A&, B&
    Const Seed1& = &H1, Seed2& = &H2
    A = Seed1 * &H3
    A = Seed2 + (A * &H8)
    If A > &H100 Then A = A - &H100       'A now 26     (&H1A)
    B = ((RShift(A, &H4) And &HF) + &H30) 'B now 49     (&H31)
    A = ((A And &HF) + &H30)              'A now 58     (&H3A)
    If A > &H39 Then A = A + &H7          'A now 65     (&H41)
    If B > &H39 Then B = B + &H7          'B remain 49  (&H31)

Now, how to get 1 and 2 back? (The value of the seeds)

    If A > &H40 Then A = A - &H7          'A now 58     (&H3A)
    If B > &H40 Then B = B - &H7          'B remain 49  (&H31)
    'Help help help


You might even beable to guess what im doing from that code :D
help help help help please!

[EDIT] ok, i see why i cant work out how to compute the seeds back now.
So, how about computeing the ascii character it pointed to in the 1st place?
List:
"246789BCDEFGHJKMNPRTVWXZ" being the string and use of InStr() -1 to point to the character.

Seed0  = &H32    ascii: 2
Seed1  = &H34    ascii: 4
Seed2  = &H36    ascii: 6
Seed3  = &H37    ascii: 7
Seed4  = &H38    ascii: 8
Seed5  = &H39    ascii: 9
Seed6  = &H42    ascii: B
Seed7  = &H43    ascii: C
Seed8  = &H44    ascii: D
Seed9  = &H45    ascii: E
Seed10 = &H46    ascii: F
Seed11 = &H47    ascii: G
Seed12 = &H48    ascii: H
Seed13 = &H4A    ascii: J
Seed14 = &H4B    ascii: K
Seed15 = &H4D    ascii: M
Seed16 = &H4E    ascii: N
Seed17 = &H50    ascii: P
Seed18 = &H52    ascii: R
Seed19 = &H54    ascii: T
Seed20 = &H56    ascii: V
Seed21 = &H57    ascii: W
Seed22 = &H58    ascii: X
Seed23 = &H5A    ascii: Z

Can anyone work this out?
And have you guess what im doing now? :)

MysT_DooM

yup the formula for private values. and sry have no idea how to help you but check this out i think this might be similar to the algorithm blizz uses.
http://en.wikipedia.org/wiki/RSA


vb6, something about that combination of numbers and letters is sexy

Ringo

Quote from: MysT_DooM on January 23, 2006, 10:32 AM
yup the formula for private values. and sry have no idea how to help you but check this out i think this might be similar to the algorithm blizz uses.
http://en.wikipedia.org/wiki/RSA
Nah, im working on a encode function for d2/d2lod/w2 cdkeys :P
Quote from: en.wikipedia.org/wiki/RSAThe algorithm was described in 1977 by Ron Rivest
lol :)

TheMinistered

You should send me a msg on aim, I can probably help you out quite a bit, don't like conversing over forums much ;p

Ringo

Quote from: TheMinistered on January 23, 2006, 04:35 PM
You should send me a msg on aim, I can probably help you out quite a bit, don't like conversing over forums much ;p
Thanks!
Thats means i got to DL Aim (unless you have MSN)
Probly here from me soon :)

Adron

#5
Read this as pseudocode or as C++, whichever you prefer.


int A, B, flag = 0;
const int seed1 = 1, seed2 = 2;
A = seed1 * 24 + seed2;
if(A >= 0x100) { A = A - 0x100; flag = 1; }
B = (A >> 4) + '0';
A = (A & 0x0f) + '0';
if(A > '9') A = A - '9' + 'A' - 1;
if(B > '9') B = B - '9' + 'A' - 1;

int seed1calc, seed2calc, temp;
if(A >= 'A') temp = A - 'A' + 10; else temp = A - '0';
if(B >= 'A') temp += B - 'A' + 10; else temp += B - '0';
if(flag) temp += 0x100;
seed1calc = temp / 24;
seed2calc = temp % 24;


Ringo

#6
Quote from: Adron on January 24, 2006, 10:35 AM
Read this as pseudocode or as C++, whichever you prefer.


int A, B, flag = 0;
const int seed1 = 1, seed2 = 2;
A = seed1 * 24 + seed2;
if(A >= 0x100) { A = A - 0x100; flag = 1; }
B = (A >> 4) + '0';
A = (A & 0x0f) + '0';
if(A > '9') A = A - '9' + 'A' - 1;
if(B > '9') B = B - '9' + 'A' - 1;

int seed1calc, seed2calc, temp;
if(A >= 'A') temp = A - 'A' + 10; else temp = A - '0';
if(B >= 'A') temp += B - 'A' + 10; else temp += B - '0';
if(flag) temp += 0x100;
seed1calc = temp / 24;
seed2calc = temp % 24;



Hi, thanks!
I notice you store a value in flag in order to know if temp has to have 0x100 taken away from it.
When encodeing there is no way of knowing if + 0x100 was used :(

Iv re-wrote the decode function from existing code, inorder to gain a better understanding of how it works, but its just this last part in the encode function, where the key values get converted back to standard key codes, is where im lost :P
Im thinking that re-createing the ascii characters is more possible than re-createing the seed values, due to the lossyness of the method used to convert the ascii characters to hex in the decode function, but this kind of mind blowed me yesterday :P

Any ideas?
thanks

Public Function DecodeD2(ByVal CDKey As String) As String
    Dim tmpByte As Byte, i%, A&, B&
    Dim Key(0 To 15) As String
    Const CodeValues As String = "246789BCDEFGHJKMNPRTVWXZ"
    For i = 1 To 16 'Fill array
        Key(i - 1) = UCase(Mid$(CDKey, i, 1))
    Next i
    Dim IntStr%(1), i2%
    For i = 0 To 15 Step 2
        For i2 = 0 To 1
            IntStr(i2) = InStr(1, CodeValues, Key(i + i2)) - 1
            If IntStr(i2) = -1 Then IntStr(i2) = &HFF
            If i2 = 0 Then A = IntStr(i2) * 3 Else A = IntStr(i2) + A * 8
        Next i2
        If A >= &H100 Then A = A - &H100
        B = ((RShift(A, 4) And &HF) + &H30)
        A = ((A And &HF) + &H30)
        If B > &H39 Then B = B + &H7
        If A > &H39 Then A = A + &H7
        Key(i) = Chr$(B)
        Key(i + 1) = Chr$(A)
    Next i
    Erase IntStr()
    Dim tmpD As String * 1
    For i = 15 To 0 Step -1
        If i > 8 Then tmpByte = ((i - 9) And &HF) Else tmpByte = ((i + 7) And &HF)
        tmpD = Key(i)
        Key(i) = Key(tmpByte)
        Key(tmpByte) = tmpD
    Next i
    Dim HashKey&
    HashKey = &H13AC9741
    For i = 15 To 0 Step -1
        tmpByte = Asc(UCase(Key(i)))
        If Val(tmpByte) <= Asc("7") Then
            Key(i) = Chr$(((HashKey And &HFF) And 7) Xor tmpByte)
            HashKey = RShift(HashKey, 3)
        ElseIf Val(tmpByte) < Asc("A") Then
            Key(i) = Chr$((i And 1) Xor tmpByte)
        Else
            Key(i) = Chr$(tmpByte)
        End If
    Next i
    DecodeD2 = Join(Key, vbNullString)
    Erase Key()
End Function




Public Function EncodeD2(ByVal CDKey As String) As String
    Dim tmpByte As Byte, i%, A&, B&
    Dim Key(0 To 15) As String
    Const CodeValues As String = "246789BCDEFGHJKMNPRTVWXZ"
    For i = 1 To 16 'Fill array
        Key(i - 1) = UCase(Mid$(CDKey, i, 1))
    Next i
    Dim HashKey&
    HashKey = &H13AC9741
    For i = 15 To 0 Step -1
        tmpByte = Asc(UCase(Key(i)))
        If Val(tmpByte) <= Asc("7") Then
            Key(i) = Chr$(((HashKey And &HFF) And 7) Xor tmpByte)
            HashKey = RShift(HashKey, 3)
        ElseIf Val(tmpByte) < Asc("A") Then
            Key(i) = Chr$((i And 1) Xor tmpByte)
        Else
            Key(i) = Chr$(tmpByte)
        End If
    Next i
    Dim tmpD As String * 1
    For i = 0 To 15
        If i > 8 Then tmpByte = ((i - 9) And &HF) Else tmpByte = ((i + 7) And &HF)
        tmpD = Key(i)
        Key(i) = Key(tmpByte)
        Key(tmpByte) = tmpD
    Next i

    For i = 0 To 15 Step 2
        B = Asc(Key(i))
        A = Asc(Key(i + 1))
        If B > &H40 Then B = B - &H7
        If A > &H40 Then A = A - &H7
        'uh
    Next i

    EncodeD2 = Join(Key, vbNullString)
    Erase Key()
End Function

Adron

If you do not know whether 0x100 was added or not, I think you do not understand the code you are copying. At least not if this is an attempt to work with the W2BNE/D2/etc cd keys. There is no way to map it to two unique seeds without that; you will necessarily have two different and equally possible options.

Ringo

Quote from: Adron on January 25, 2006, 09:29 AM
If you do not know whether 0x100 was added or not, I think you do not understand the code you are copying. At least not if this is an attempt to work with the W2BNE/D2/etc cd keys. There is no way to map it to two unique seeds without that; you will necessarily have two different and equally possible options.
I understand it, that is not the problem, the problem is reverseing the effects of it.
The only thing im left to do to encode a decoded cdkey into a encoded cdkey again, is to convert the bytes back to key code characters: "246789BCDEFGHJKMNPRTVWXZ"
Like for example, if the my cdkey started with "46" it would be classed as 1 and 2 on the 1st loop as you can see below:

    Const CodeValues As String = "246789BCDEFGHJKMNPRTVWXZ"
    Dim IntStr%(1), i2%
    For i = 0 To 15 Step 2
        For i2 = 0 To 1
            IntStr(i2) = InStr(1, CodeValues, Key(i + i2)) - 1
            If IntStr(i2) = -1 Then IntStr(i2) = &HFF
            If i2 = 0 Then A = IntStr(i2) * 3 Else A = IntStr(i2) + A * 8
        Next i2
        '//IntStr(0) is 1 from CodeValues string location -1
        '//IntStr(1) is 2 from CodeValues string location -1
        '//A = 1 * 3
        '//A = 2 + A * 8
        If A >= &H100 Then A = A - &H100
        B = ((RShift(A, 4) And &HF) + &H30)
        A = ((A And &HF) + &H30)
        If B > &H39 Then B = B + &H7
        If A > &H39 Then A = A + &H7
        Key(i) = Chr$(B)
        Key(i + 1) = Chr$(A)
    Next i

And unless im missing something which is more than possible with my maths, IntStr(0) and IntStr(1) can not be computed back efficantly, because when there righshifted and and'ed down, bits can be lost.
So the only way i see possible to correctly encode the cdkey, is to *some how* compute the characters in CodeValues string, because getting the location in the string where they are from looks impossible.
Im not sure if iv ported this to VB6 correctly, but if i have, it shows it to:


    Dim tmp As Long
    If A >= Asc("A") Then tmp = A - Asc("A") + 10 Else tmp = A - Asc("0")
    If B >= Asc("A") Then tmp = tmp + B - Asc("A") + 10 Else tmp = tmp + B - Asc("0")
    'If tmp <= &H100 Then tmp = tmp + &H100
    A = (tmp / 24)
    B = (tmp Mod 24)
    '//A = 0    //If +0x100 A = 11
    '//B = 11   //If +0x100 B = 3


You can test the decode and encode functions out if you want, the decode one works perfectly, and the endcode function unhash the key, reshuffle it back into the correct order, but cant do the converting part :P

If im missing somthing can you please explain?
Im more than hapy/wanting to learn more.

Thanks

Adron

When I checked the encoding/decoding of cd keys, the flag indicating whether 0x100 had been subtracted or not was saved into a variable in Blizzard's version of the code.

Ringo

#10
Oh, im following now.
l)ragon PM'ed me a compleat decode function this morning (thanks l)ragon), and it has the valid check in it.
Iv had a hard re-think, and even being able to extract the flag, to know if 0x100 needs to be added or not and knowing where in the key, its looks to be impossible to compute the character locations in the KeyValues string. :(

[EDIT]:
I just tryed a idea out in the hope i could make a byte array table, but it has become very clear why its not possible :(
After making a 24 * 24 table with all possible key values, it shows exacly how much bits are really being lost when the key characters get converted into hex.
(I wont post all of it, just the part where it becomes clear)

Instr() -1 location of key character
        Converted hex result
             Had 0x100 Taken From
00/00 = 0/0  False
00/01 = 1/0  False
00/02 = 2/0  False
00/03 = 3/0  False
00/04 = 4/0  False
00/05 = 5/0  False
00/06 = 6/0  False
00/07 = 7/0  False
00/08 = 8/0  False
00/09 = 9/0  False
00/10 = A/0  False
00/11 = B/0  False
00/12 = C/0  False
00/13 = D/0  False
00/14 = E/0  False
00/15 = F/0  False



10/16 = 0/0  True
10/17 = 1/0  True
10/18 = 2/0  True
10/19 = 3/0  True
10/20 = 4/0  True
10/21 = 5/0  True
10/22 = 6/0  True
10/23 = 7/0  True
11/00 = 8/0  True
11/01 = 9/0  True
11/02 = A/0  True
11/03 = B/0  True
11/04 = C/0  True
11/05 = D/0  True
11/06 = E/0  True
11/07 = F/0  True



21/08 = 0/0  True
21/09 = 1/0  True
21/10 = 2/0  True
21/11 = 3/0  True
21/12 = 4/0  True
21/13 = 5/0  True
21/14 = 6/0  True
21/15 = 7/0  True
21/16 = 8/0  True
21/17 = 9/0  True
21/18 = A/0  True
21/19 = B/0  True
21/20 = C/0  True
21/21 = D/0  True
21/22 = E/0  True
21/23 = F/0  True


Is this a loseing battle? :(
The only way i can see this to be possible is that the cdkeys them selfs have to be layed out in some kind of order, as in there is another value calced from the other characters (like the KeyFlag) or somthing  :-\

Any suggestions/ideas? :(
Thanks for helping btw

Adron

There is one flag for each pair of letters. Not just one flag for the whole cd key. If that is what you are stuck on.

Ringo

#12
Quote from: Adron on January 26, 2006, 10:20 AM
There is one flag for each pair of letters. Not just one flag for the whole cd key. If that is what you are stuck on.

    R = 3
    For i = 0 To 15
        R = R + (GetNumValue(Key(i)) Xor (R * 2))
    Next i
    R = R And &HFF
    '//flag extracted to R (valid check if decodeing)
    KeyFlag = &H80 'flag seed
    Dim tmp&
    For i = 14 To 0 Step -2
        B = Asc(Key(i))
        A = Asc(Key(i + 1))
        If A >= Asc("A") Then tmp = A - Asc("A") + 10 Else tmp = A - Asc("0")
        If B >= Asc("A") Then tmp = tmp + B - Asc("A") + 10 Else tmp = tmp + B - Asc("0")
        If R And KeyFlag Then
            A = A + &H100
            R = R - KeyFlag
        End If
        A = (tmp / 24)
        B = (tmp Mod 24)
        Key(i) = Mid(CodeValues, B + 1, 1)
        Key(i + 1) = Mid(CodeValues, A + 1, 1)
        KeyFlag = KeyFlag / 2
    Next i

Iv got that figgerd already, but hows that flag used other than to know if it needs 0x100 taken away?
If it isnt, then it leaves a single byte vs 570 somthing possible combinations, making it not possible :(

Adron

Well, looking at that code, it seems you have the flag figured fine...

Ringo

#14
Hmm, iv thought about it in as many ways as i can, and i *think* each 2 characters can not go any higher than "WC" (21/7) -- 0x1FF, based on how the flag gets calced and space given.
If they can go higher than that, then there is no space and its back to square one :(
Iv only got around 20 d2/w2 keys, and i did find one with "WC" but non higher, so its kind of shit or bust. :P

Thanks for helping Adron, and l)ragon for the compleat decode function.


    '//flag extract
    R = 3
    For i = 0 To 15
        R = R + (GetNumValue(Key(i)) Xor (R * 2))
    Next i
    R = R And &HFF
    tmpByte = &H80 'seed the flag
    '//convert hex to KeyCodes
    For i = 14 To 0 Step -2
        A = GetNumValue(Key(i))
        B = GetNumValue(Key(i + 1))
        A = CLng("&H" & Hex(A) & Hex(B))
        If R And tmpByte Then A = A + &H100
        Call KeyCodeOffSets(A, B)
        Key(i) = Mid(KeyCodes, B + 1, 1)
        Key(i + 1) = Mid(KeyCodes, A + 1, 1)
        tmpByte = tmpByte / 2 'downgrade flag
    Next i


Private Sub KeyCodeOffSets(Bit1&, Bit2&)
    Bit2 = 0
    While Bit1 >= &H18
        Bit2 = Bit2 + 1
        Bit1 = Bit1 - &H18
    Wend
End Sub