Old 8th April 2015, 01:28   #1
Sockets
Junior Member
 
Join Date: Sep 2012
Posts: 36
XTEA AuthBlob

I'm reading the Ultravox 2.1 documentation, and I've actually got a program working so far.
My problem lies in the Authentication.

I've found a C# implementation of the XTEA algorithm and all seems well right up to the point where I use the goddamn thing.

code:

static void encrypt(uint[] v, uint[] k)
{
uint y = v[0];
Console.WriteLine(Convert.ToString(v[1]);
uint z = v[1];
uint sum = 0;
uint delta = 0x9E3779B9;
uint n = 32;

while (n-- > 0)
{
y += (z << 4 ^ z >> 5) + z ^ sum + k[sum & 3];
Console.WriteLine(y);
sum += delta;
z += (y << 4 ^ y >> 5) + y ^ sum + k[sum >> 11 & 3];
Console.WriteLine(z);
}

v[0] = y;
v[1] = z;
}



A couple of things don't make sense:

How do I get my information (uid and password) into uint[] format? I assumed that I should put it into byte[]'s, but I can't convert these into uints due to size restrictions, endianness, etc.
Since when are there two elements for v[]? It really bugs me how there's no goddamn explanation for this. VAGUE.
Where is the return? If I don't get anything back, how am I supposed to get the information and send it?

Honestly, this wiki really needs cleaning up and explanation. It's quite inadequate and vague. It's extremely frustrating and it's like it was written in some wild, coke-fueled sitting.

I should hope the developers will be wiser next time and decide in favor of a stronger algorithm that doesn't include a PUBLIC DECRYPTION FUNCTION (yes, it can be decrypted with a function that is available on the web)...

Just some things to consider :/


If available, I'd really just appreciate someone's working implementation of the authblob aspects. That's all I need.
Sockets is offline   Reply With Quote
Old 8th April 2015, 01:53   #2
DrO
 
Join Date: Sep 2003
Posts: 27,873
the choice of protocol implementation details were dictated by decisions stemming back to 2004 (possibly earlier) and so what there is now is what we're stuck with. as it was never intended as a secure system but just as something that better fitted in with what AOL were using (based on what I gathered) and which resolved the main issues with the 1.x protocol. and that happened to require the adaptation of an earlier version of the ultravox 2 protocol which used what you now see. as i'd already said here.

not that there's much point in adopting the 2.x protocol now as it's becoming more obvious that it is at odds with the shift to HTML5 audio players and the latest DNAS release (2.4.7 or newer depending on when people read this) resolves the main issue in getting multiple direct sources into the DNAS via manipulation of the source password (which was the only true remaining benefit of the 2.x protocol). thus making the even more insecure 1.x protocol remaining the version of choice for source connections (as that's what people want and what those developing (or rather not developing) source clients have led things to be).


and yes, the docs are a complete mess but that's all there is (as came from AOL) and it should be improved (which I've failed to do) but even if that were to be done, it pretty much won't help much with your question as I don't remember enough C# (it's been over 5 years since I touched C#) to be able to answer your question on what you need to cast / convert things to to get it working. as what is posted is the working C++ code but maybe there is a working C# version somewhere (it won't have come from us as the DNAS is C++).


so I'm sorry but for what you've asked for help with, maybe someone else can chip in on how to do it via C# if that's what you want to do (or you find an example), but it's not something I can answer / provide you with a working example off other than the C++ that is currently provided.
DrO is offline   Reply With Quote
Old 8th April 2015, 03:40   #3
Sockets
Junior Member
 
Join Date: Sep 2012
Posts: 36
Quote:
Originally Posted by DrO View Post
the choice of protocol implementation details were dictated by decisions stemming back to 2004 (possibly earlier) and so what there is now is what we're stuck with. as it was never intended as a secure system but just as something that better fitted in with what AOL were using (based on what I gathered) and which resolved the main issues with the 1.x protocol. and that happened to require the adaptation of an earlier version of the ultravox 2 protocol which used what you now see. as i'd already said here.

not that there's much point in adopting the 2.x protocol now as it's becoming more obvious that it is at odds with the shift to HTML5 audio players and the latest DNAS release (2.4.7 or newer depending on when people read this) resolves the main issue in getting multiple direct sources into the DNAS via manipulation of the source password (which was the only true remaining benefit of the 2.x protocol). thus making the even more insecure 1.x protocol remaining the version of choice for source connections (as that's what people want and what those developing (or rather not developing) source clients have led things to be).


and yes, the docs are a complete mess but that's all there is (as came from AOL) and it should be improved (which I've failed to do) but even if that were to be done, it pretty much won't help much with your question as I don't remember enough C# (it's been over 5 years since I touched C#) to be able to answer your question on what you need to cast / convert things to to get it working. as what is posted is the working C++ code but maybe there is a working C# version somewhere (it won't have come from us as the DNAS is C++).


so I'm sorry but for what you've asked for help with, maybe someone else can chip in on how to do it via C# if that's what you want to do (or you find an example), but it's not something I can answer / provide you with a working example off other than the C++ that is currently provided.

No problem. I may help out and take a crack at it and place in what I know.

The current C++ example would do fine if it had an explanation on how you put in the parameters, like how you get them. Is there any way for someone to address the non-C# aspects of my question?

EDIT: Never mind. Apparently editing is restricted to admins. :/
Sockets is offline   Reply With Quote
Old 8th April 2015, 09:24   #4
jaromanda
Forum King
 
Join Date: Jun 2007
Location: Under the bridge
Posts: 2,289
Quote:
Originally Posted by Sockets View Post
I've found a C# implementation of the XTEA algorithm
what you've posted is a small part of it then
Quote:
How do I get my information (uid and password) into uint[] format?
First, convert the string to a byte array
code:

static byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}


Next, you'll need to pad out the byte array to a multiple of 8 bytes (16 bytes in the case of the key), or, preferably, change that function to pad out the bytes as required

Then, you can use BitConverter.ToUInt32 to convert the byte array to a uint32 array, both for the data and the key (the key will always be 4 UInt32 values, no more, no less)

Then you call your function for every pair of UInt32's in your data

There's probably far more elegant ways of doing the above in C#, but that should get you going
Quote:
Since when are there two elements for v[]?
XTEA encrypts in blocks of 8 bytes, i.e. two UInt32's at a time, hence the v[] array is always 2 elements long

the code you posted handles encryption of a single block

and FYI, only the first 16 bytes (4 x UInt32) of the key are used for encryption

Is it just me or are shoutcast users getting dumber?
jaromanda is offline   Reply With Quote
Old 8th April 2015, 11:00   #5
jaromanda
Forum King
 
Join Date: Jun 2007
Location: Under the bridge
Posts: 2,289
hmmm ... endienness may be an issue with the function I posted. you may need to do it the "long" way,

Is it just me or are shoutcast users getting dumber?
jaromanda is offline   Reply With Quote
Old 8th April 2015, 12:27   #6
Sockets
Junior Member
 
Join Date: Sep 2012
Posts: 36
Ah thank you so much! I new I had to do some conversions but I was worried about the size of the arrays not being consistent.
Sockets is offline   Reply With Quote
Old 9th April 2015, 13:05   #7
Sockets
Junior Member
 
Join Date: Sep 2012
Posts: 36
Well now it's just giving me the wrong info.
http://pastebin.com/T2mKvNdS

I'm encrypting "touch123" with key "foobar", the same key used by the shoutcast server. :/ The output doesn't match the hex representation of the packet nor does it represent the hash found in the packet.
Sockets is offline   Reply With Quote
Old 10th April 2015, 08:59   #8
jaromanda
Forum King
 
Join Date: Jun 2007
Location: Under the bridge
Posts: 2,289
dissecting your code

uKeyArray is initialised but never populated with anything

the foreach loop does nothing with the first four bytes of the key, converts the remaining bytes to Uint32 ... and does nothing with the result

edit: scratch that ... the foreach loop does nothing at all, because i will never be > 4

the encrypt function looks ok, though, what the index parameter is meant to achieve is a mystery to me

Is it just me or are shoutcast users getting dumber?
jaromanda is offline   Reply With Quote
Old 10th April 2015, 12:59   #9
Sockets
Junior Member
 
Join Date: Sep 2012
Posts: 36
Quote:
Originally Posted by jaromanda View Post
dissecting your code

uKeyArray is initialised but never populated with anything

the foreach loop does nothing with the first four bytes of the key, converts the remaining bytes to Uint32 ... and does nothing with the result

edit: scratch that ... the foreach loop does nothing at all, because i will never be > 4

the encrypt function looks ok, though, what the index parameter is meant to achieve is a mystery to me
EDIT: nope I was being stupid again

Corrected code:
http://pastebin.com/4Nj7Zw8Z

Also, this is the output I'm trying to get. I retrieved it from Wireshark, using SAM to connect.

Plaintext Hash: 78f7a61937b58946
Bytes: 37 38 66 37 61 36 31 39 33 37 62 35 38 39 34 36

How exactly is the hash derived?
Sockets is offline   Reply With Quote
Old 10th April 2015, 23:56   #10
jaromanda
Forum King
 
Join Date: Jun 2007
Location: Under the bridge
Posts: 2,289
Quote:
Originally Posted by Sockets View Post
Also, this is the output I'm trying to get. I retrieved it from Wireshark, using SAM to connect.

Plaintext Hash: 78f7a61937b58946
Bytes: 37 38 66 37 61 36 31 39 33 37 62 35 38 39 34 36

How exactly is the hash derived?
the result of xtea encryption converted to hex

Is it just me or are shoutcast users getting dumber?
jaromanda is offline   Reply With Quote
Old 11th April 2015, 00:05   #11
jaromanda
Forum King
 
Join Date: Jun 2007
Location: Under the bridge
Posts: 2,289
You've also misunderstood a couple of things, or i may be misunderstanding the code (looks like c#?)

the key is 16 bytes (padded out with nulls or truncated as required)

you do not take the first 4 bytes of the key and extend each of those to a uint32 ...

you convert the first 4 bytes to a uint32, then the next 4 bytes to the second uint32, and so on for 16 bytes

i.e. ... foobar in hex representation is

66 6f 6f 62 61 72

padded out to 16 bytes that's

66 6f 6f 62 - 61 72 00 00 - 00 00 00 00 - 00 00 00 00

your key would be

0x666f6f62, 0x61720000, 0x00000000 0x00000000

your code seems to create the key

0x00000066, 0x0000006f, 0x0000006f, 0x00000062


note the endianness . I think your conversion later on of the data will be wrong as int's are stored little endian on x86 architecture, so merely "mapping" a uint32 over the memory used by a string will result in the wrong values for your uint32's - you seem to be using https://code.google.com/p/opentibiax...graphy/Xtea.cs as a basis for your encrypt function, but that looks wrong to me - however, I can't say I know C# well

Is it just me or are shoutcast users getting dumber?
jaromanda is offline   Reply With Quote
Old 11th April 2015, 00:50   #12
Sockets
Junior Member
 
Join Date: Sep 2012
Posts: 36
Quote:
Originally Posted by jaromanda View Post
the result of xtea encryption converted to hex
edit: reading above
Sockets is offline   Reply With Quote
Old 11th April 2015, 06:57   #13
Sockets
Junior Member
 
Join Date: Sep 2012
Posts: 36
Quote:
Originally Posted by jaromanda View Post
You've also misunderstood a couple of things, or i may be misunderstanding the code (looks like c#?)

the key is 16 bytes (padded out with nulls or truncated as required)

you do not take the first 4 bytes of the key and extend each of those to a uint32 ...

you convert the first 4 bytes to a uint32, then the next 4 bytes to the second uint32, and so on for 16 bytes

i.e. ... foobar in hex representation is

66 6f 6f 62 61 72

padded out to 16 bytes that's

66 6f 6f 62 - 61 72 00 00 - 00 00 00 00 - 00 00 00 00

your key would be

0x666f6f62, 0x61720000, 0x00000000 0x00000000

your code seems to create the key

0x00000066, 0x0000006f, 0x0000006f, 0x00000062


note the endianness . I think your conversion later on of the data will be wrong as int's are stored little endian on x86 architecture, so merely "mapping" a uint32 over the memory used by a string will result in the wrong values for your uint32's - you seem to be using https://code.google.com/p/opentibiax...graphy/Xtea.cs as a basis for your encrypt function, but that looks wrong to me - however, I can't say I know C# well
Ok I finally understand all of this and I have DEFINITELY corrected my code...


..but how do I turn these separated bytes into 0x666f6f62, 0x61720000, 0x00000000 0x00000000? I heard from somewhere that I should use bitwise or, but I'm not familiar with that.

code:

byte[] keyBytes = new byte[16];
keyBytes = Encoding.ASCII.GetBytes(keyStr);
uint[] k = new uint[4];
......?

Sockets is offline   Reply With Quote
Old 11th April 2015, 08:29   #14
jaromanda
Forum King
 
Join Date: Jun 2007
Location: Under the bridge
Posts: 2,289
I'll show you my javascript code, but not sure it would help at all http://pastebin.com/rZwexkTD

Is it just me or are shoutcast users getting dumber?
jaromanda is offline   Reply With Quote
Old 11th April 2015, 15:21   #15
Sockets
Junior Member
 
Join Date: Sep 2012
Posts: 36
Quote:
Originally Posted by jaromanda View Post
I'll show you my javascript code, but not sure it would help at all http://pastebin.com/rZwexkTD
Yeah there's too much inconsistency with C# for it to be incredibly helpful. Especially without any type declarations in the functions (type it returns)..
Sockets is offline   Reply With Quote
Old 12th April 2015, 01:28   #16
jaromanda
Forum King
 
Join Date: Jun 2007
Location: Under the bridge
Posts: 2,289
reversing uint's is a breeze with IPAddress.HostToNetworkOrder

Is it just me or are shoutcast users getting dumber?
jaromanda is offline   Reply With Quote
Old 12th April 2015, 18:52   #17
Sockets
Junior Member
 
Join Date: Sep 2012
Posts: 36
Ok. This is my new code:

http://pastebin.com/HkxGrUp6

It does everything properly, except encrypt information. I get the wrong result.

How do I grab that hash?
Sockets is offline   Reply With Quote
Old 13th April 2015, 03:44   #18
jaromanda
Forum King
 
Join Date: Jun 2007
Location: Under the bridge
Posts: 2,289
That's not right, you can't reverse the whole data array, you reverse every four bytes, and the output has to be hexadecimal representation of the byte data

Is it just me or are shoutcast users getting dumber?
jaromanda is offline   Reply With Quote
Old 13th April 2015, 03:53   #19
jaromanda
Forum King
 
Join Date: Jun 2007
Location: Under the bridge
Posts: 2,289
I guess you could:

add any required padding to the bytes

if littleendian, reverse the bytes

convert the bytes to uint32's

if littleendian, reverse the array of uint32's

Is it just me or are shoutcast users getting dumber?
jaromanda is offline   Reply With Quote
Old 13th April 2015, 12:57   #20
Sockets
Junior Member
 
Join Date: Sep 2012
Posts: 36
Quote:
Originally Posted by jaromanda View Post
I guess you could:

add any required padding to the bytes

if littleendian, reverse the bytes

convert the bytes to uint32's

if littleendian, reverse the array of uint32's
Yeah that's what I'm doing.

This should work for the reversal, no?

code:
for (int i = 0; i < 4; i++)
{
Array.Reverse(keyBytes, i * 4, 4);
keyArr[i] = BitConverter.ToUInt32(keyBytes, i * 4);
}



I'll put an if conditional in there later.
Sockets is offline   Reply With Quote
Old 13th April 2015, 22:00   #21
jaromanda
Forum King
 
Join Date: Jun 2007
Location: Under the bridge
Posts: 2,289
Quote:
Originally Posted by Sockets View Post
Yeah that's what I'm doing.
Not in the code you linked, you're reversing the order of the byte array, then converting that to an array of uint32's - which is not the same as what I said

Is it just me or are shoutcast users getting dumber?
jaromanda is offline   Reply With Quote
Old 14th April 2015, 14:35   #22
Sockets
Junior Member
 
Join Date: Sep 2012
Posts: 36
Quote:
Originally Posted by jaromanda View Post
Not in the code you linked, you're reversing the order of the byte array, then converting that to an array of uint32's - which is not the same as what I said
Right I corrected it with the for loop.
Sockets is offline   Reply With Quote
Old 15th April 2015, 02:35   #23
Sockets
Junior Member
 
Join Date: Sep 2012
Posts: 36
It's still not working. What am I missing about the output?
Sockets is offline   Reply With Quote
Old 15th April 2015, 06:19   #24
jaromanda
Forum King
 
Join Date: Jun 2007
Location: Under the bridge
Posts: 2,289
if it's anything like the code you've posted so far, you need to output the encrypted bytes in hexadecimal

Is it just me or are shoutcast users getting dumber?
jaromanda is offline   Reply With Quote
Old 15th July 2015, 11:17   #25
bored_womble
Winamp's Womble
 
bored_womble's Avatar
 
Join Date: May 2004
Location: Wimbledon Common
Posts: 1,100
a java example - if it helps

You can use the pad code in the working AOL Xtea code below and do something like

if cypherResponse was the byte array containing the response then

code:
Encrypt myCrypter = new Encrypt();
byte[] paddedKey = myCrypter.pad(cypherResponse,16,(byte)0x00);
myCrypter.xteaInit(paddedKey);



I have expanded parts of the code to make it more 'readable' although there was only so far you can go with that kind of thing.

Hope this helps,

BW


code:

package com.aol.xtea;

/**
* An implementation of the XTEA block cipher algorithm for Shoutcast Ultravox.
*/
public class Encrypt {

private final int
ROUNDS = 32, // iteration count (cycles)
BLOCK_SIZE = 8, // bytes in a data block (64 bits)
DELTA = 0x9E3779B9,
D_SUM = 0xC6EF3720;

private int[] S = new int[4];

private boolean decrypt = false;

public Encrypt ( )
{
}

public void xteaInit(byte[] key)
{ generateSubKeys(key); }

public String encryptString(String toEncrypt)
{
int cL = toEncrypt.length();
int cM = cL % 8;
int base = 8 - cM;

if ( base == 8)
base = 0;

String ret = "";
byte[] PaddedReady = pad(toEncrypt, cL+base, (byte)0x00);
for (int loop=0; loop<(cL+(int)base)/8 ; loop++ )
{
byte[] encoded = xteaCrypt(PaddedReady,loop*8);
for ( int c=0; c<encoded.length; c++ )
{
int eme = (int)encoded[c];
eme = eme & 0xFF;
String ehe = Integer.toHexString(eme);
if ( ehe.length() < 2 )
ehe = "0"+ehe;
ret+=ehe;
}
}
return ret;
}

public byte[] xteaCrypt(byte[] in, int tap) {

int v0 = (int)in[tap] & 0x0ff; v0 = v0 << 8; tap++;
v0 += (int)in[tap] & 0x0ff; v0 = v0 << 8; tap++;
v0 += (int)in[tap] & 0x0ff; v0 = v0 << 8; tap++;
v0 += (int)in[tap] & 0x0ff; tap++;

int v1 = (int)in[tap] & 0x0ff; v1 = v1<< 8; tap++;
v1 += (int)in[tap] & 0x0ff; v1 = v1 << 8; tap++;
v1 += (int)in[tap] & 0x0ff; v1 = v1 << 8; tap++;
v1 += (int)in[tap] & 0x0ff; tap++;

int n = ROUNDS, sum;

if (!decrypt) {
sum = 0;

while (n-- > 0) {
v0 += ((v1 << 4 ^ v1 >>> 5) + v1) ^ (sum + S[sum & 3]);
sum += DELTA;
v1 += ((v0 << 4 ^ v0 >>> 5) + v0) ^ (sum + S[sum >> 11 & 3]);
}
} else {
sum = D_SUM;

while (n-- > 0) {
v1 -= ((v0 << 4 ^ v0 >>> 5) + v0) ^ (sum + S[sum >> 11 & 3]);
sum -= DELTA;
v0 -= ((v1 << 4 ^ v1 >>> 5) + v1) ^ (sum + S[sum & 3]);
}
}

int outOffset = 0;
byte[] out = new byte[BLOCK_SIZE];


out[outOffset++] = (byte)(v0 >>> 24);
out[outOffset++] = (byte)(v0 >>> 16);
out[outOffset++] = (byte)(v0 >>> 8);
out[outOffset++] = (byte)(v0 );

out[outOffset++] = (byte)(v1 >>> 24);
out[outOffset++] = (byte)(v1 >>> 16);
out[outOffset++] = (byte)(v1 >>> 8);
out[outOffset++] = (byte)(v1 );

return out;
}

public void generateSubKeys(byte[] key)
{
int off = 0;
for(int i=0; i<4; i++)
{
S[i] = key[off]; off++;
S[i] = S[i] << 8;
S[i] += key[off]; off++;
S[i] = S[i] << 8;
S[i] += key[off]; off++;
S[i] = S[i] << 8;
S[i] += key[off]; off++;

}

}


public byte[] pad(String str, int size, byte padChar)
{
byte[] returnByte = new byte[size];
byte[] thisString = str.getBytes();
for (int a=0; a<thisString.length; a++ )
{ returnByte[a] = thisString[a]; }
// Remember to pad with padChar
int remainder = size - str.length();
for ( int r =0 ; r<remainder; r++ )
{
returnByte[(thisString.length+r)] = padChar;
}

return returnByte;

}
}


Without open minds the world will die. Open yours and correct the mistakes you are making right now.
bored_womble is offline   Reply With Quote
Reply
Go Back   Winamp & Shoutcast Forums > Shoutcast > Shoutcast Technical Support

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump