unknown packets sent by Flash - java

I'm learning about Flash (AMF) and Java (BlazeDS) using the project I found on the internet, but I noticed that the server is receiving via socket the data below:
When I tried to use the Amf0Input/Amf3Input me to return the object, I get an error that does not recognize this type of package. Anyone know which library should I use to decode this message?

The packet you got seems to be a length prefixed AMF3 AmfObject.
In general, whenever you see a string that follows the usual naming convention of fully qualified class names (i.e. like reverse domains), chances are you're dealing with an object instance1.
Looking at the first few bytes, you see 0x00 repeated three times. If we assume AMF3, this would be 3 undefineds, followed by an object with type marker 0x3e - which does not exist. If we instead assume AMF0, we would first have a number (0x00 type marker, followed by 8 bytes of data), followed by an object with type marker 0x6d - which again does not exist.
Thus, the data you got there can't be AMF payload alone. However, if we interpret the first 4 bytes as network byte order (i.e. big endian) integer, we get 0x3E = 62 - which is exactly the length of the remaining data.
Assuming then that the first 4 bytes are just a length prefix, the next byte must be a type marker. In AMF3, 0x0a indicates an object instance. So lets just try to decode the remaining data (section 3.12 of the AMF3 spec, if you want to follow along2): the next byte must indicate the object traits. 0x23 means we have a direct encoding of the traits in that byte - as opposed to a reference to earlier submitted traits.
Since the fourth bit (counted from least significant first) is 0, the object is not dynamic - as in, an instance of some class, not just a plain object instance. The remaining bits, shifted to the right by 4, indicate the number of sealed properties this instance has, which is 2.
Next, we expect the classname, encoded as UTF-8-vr - i.e. length prefixed (when shifted right by 1), UTF-8 encoded string. The next byte is 0x1d, which means the length is 0x1d >> 1 = 14. The next 14 bytes encode common.net.APC, so that's the instance's class name.
Afterwards, we have the two sealed property names, also encoded as UTF-8-vr. The first one has a prefix of 0x15, so a length of 10 - giving us parameters, followed by a prefix of 0x19 (length 12) and payload functionName.
After this, you have the values corresponding to these sealed properties, in the same order. The first one has a type marker of 0x09, which corresponds to an array. The length marker is 0x03, which means the array contains one element, and the next byte is 0x01, indicating we have no associative members. The only element itself has a type marker of 0x04, meaning it's an integer - in this case with value 0.
This is followed by a type marker of 0x06 - a string, with length 14. That string - you probably have guessed it by now - is syncServerTime.
So, in summary, your packet is a length-prefixed instance of common.net.APC, with it's parameters attribute set to [0], and the functionName attribute set to "syncServerTime".
1: The only other alternatives are a vector of object instances - which would require a type marker of 0x10 somewhere - or an AMF0 packet. In the case of an AMF0 packet, you'd also have to have a URI-style path somewhere in the packet, which is not the case here.
2: Note that the EBNF given at the end of the section is not exactly correct - neither syntactically nor semantically ...

Related

Generate Ethereum addresses in HD Wallet using public key only (bitcoinj/web3j)

I trying to generate Ethereum addresses for the HD Wallet keys implemented with bitcoinj library, but I got confused:
DeterministicSeed seed = new DeterministicSeed("some seed code here", null, "", 1409478661L);
DeterministicKeyChain chain = DeterministicKeyChain.builder().seed(seed).build();
DeterministicKey addrKey = chain.getKeyByPath(HDUtils.parsePath("M/44H/60H/0H/0/0"), true);
System.out.println("address from pub=" + Keys.getAddress(Sign.publicKeyFromPrivate(addrKey.getPrivKey())));
this code prints a correct Ethereum address accordingly to https://iancoleman.io/bip39/. Everything is fine here.
But when I trying to avoid private key usage and generate non-hardened keys using public keys only I getting different results, i.e. the call returns another result:
System.out.println("address from pub=" + Keys.getAddress(addrKey.getPublicKeyAsHex()));
And it looks like the issue is in the "different public keys", i.e. result of the Sign.publicKeyFromPrivate(addrKey.getPrivKey()) and addrKey.getPublicKeyAsHex() are different.
I'm not experienced with cryptography, thus it may be a silly question... but I would appreciate any advice here.
Like Bitcoin, Ethereum uses secp256k1. Ethereum addresses are derived as follows:
Step 1: The 32 bytes x and y coordinate of the public key are concatenated to 64 bytes (where both the x and y coordinate are padded with leading 0x00 values if necessary).
Step 2: From this the Keccak-256 hash is generated.
Step 3: The last 20 bytes are used as the Ethereum address.
For the examples used here, the key is generated with:
String mnemonic = "elevator dinosaur switch you armor vote black syrup fork onion nurse illegal trim rocket combine";
DeterministicSeed seed = new DeterministicSeed(mnemonic, null, "", 1409478661L);
DeterministicKeyChain chain = DeterministicKeyChain.builder().seed(seed).build();
DeterministicKey addrKey = chain.getKeyByPath(HDUtils.parsePath("M/44H/60H/0H/0/0"), true);
This corresponds to the following public key and Ethereum address:
X: a35bf0fdf5df296cc3600422c3c8af480edb766ff6231521a517eb822dff52cd
Y: 5440f87f5689c2929542e75e739ff30cd1e8cb0ef0beb77380d02cd7904978ca
Address: 23ad59cc6afff2e508772f69d22b19ffebf579e7
as can also be verified with the website https://iancoleman.io/bip39/.
Step 1:
In the posted question, the expressions Sign.publicKeyFromPrivate() and addrKey.getPublicKeyAsHex() provide different results. Both functions return the public key in different types. While Sign.publicKeyFromPrivate() uses a BigInteger, addrKey.getPublicKeyAsHex() provides a hex string. For a direct comparison, BigInteger can be converted to a hex string with toString(16). When the results of both expressions are displayed with:
System.out.println(Sign.publicKeyFromPrivate(addrKey.getPrivKey()).toString(16));
System.out.println(addrKey.getPublicKeyAsHex());
the following result is obtained:
a35bf0fdf5df296cc3600422c3c8af480edb766ff6231521a517eb822dff52cd5440f87f5689c2929542e75e739ff30cd1e8cb0ef0beb77380d02cd7904978ca
02a35bf0fdf5df296cc3600422c3c8af480edb766ff6231521a517eb822dff52cd
The output of Sign.publicKeyFromPrivate() has a length of 64 bytes and corresponds to the concatenated x and y coordinate as defined in step 1. Therefore, the address generated with this is a valid Ethereum address, as also described in the posted question.
The output of addrKey.getPublicKeyAsHex(), on the other hand, corresponds to the x coordinate prefixed with a 0x02 value. This is the compressed format of the public key. The leading byte has either the value 0x02 if the y value is even (as in this example), or the value 0x03. Since the compressed format does not contain the y coordinate, this cannot be used to directly infer the Ethereum address, or if it is done anyway, it will result in a wrong address (indirectly, of course, it would be possible since the y coordinate can be derived from a compressed public key).
The uncompressed format of the public key can be obtained, e.g. with addrKey.decompress():
System.out.println(addrKey.decompress().getPublicKeyAsHex());
which gives this result:
04a35bf0fdf5df296cc3600422c3c8af480edb766ff6231521a517eb822dff52cd5440f87f5689c2929542e75e739ff30cd1e8cb0ef0beb77380d02cd7904978ca
The uncompressed format consists of a leading marker byte with the value 0x04 followed by the x and y coordinates. So if the leading marker byte is removed, just the data according to step 1 is obtained, which is needed for the derivation of the Ethereum address:
System.out.println(addrKey.decompress().getPublicKeyAsHex().substring(2));
which results in:
a35bf0fdf5df296cc3600422c3c8af480edb766ff6231521a517eb822dff52cd5440f87f5689c2929542e75e739ff30cd1e8cb0ef0beb77380d02cd7904978ca
Steps 2 and 3:
Steps 2 and 3 are performed by Keys.getAddress(). This allows the Ethereum address to be obtained using the uncompressed public key as follows:
System.out.println(Keys.getAddress(addrKey.decompress().getPublicKeyAsHex().substring(2)));
System.out.println(Keys.getAddress(Sign.publicKeyFromPrivate(addrKey.getPrivKey()))); // For comparison
which gives the Ethereum address:
23ad59cc6afff2e508772f69d22b19ffebf579e7
23ad59cc6afff2e508772f69d22b19ffebf579e7
Overloads of Keys.getAddress():
Keys.getAddress() provides various overloads for the data types BigInteger, hex string and byte[]. If the uncompressed key is given as byte[], e.g. with addrKey.getPubKeyPoint().getEncoded(false), the byte[] can be used directly after removing the marker byte. Alternatively, the byte[] can be converted to a BigInteger with the marker byte removed:
byte[] uncompressed = addrKey.getPubKeyPoint().getEncoded(false);
System.out.println(bytesToHex(Keys.getAddress(Arrays.copyOfRange(uncompressed, 1, uncompressed.length))).toLowerCase()); // bytesToHex() from https://stackoverflow.com/a/9855338
System.out.println(Keys.getAddress(new BigInteger(1, uncompressed, 1, uncompressed.length - 1)));
System.out.println(Keys.getAddress(Sign.publicKeyFromPrivate(addrKey.getPrivKey()))); // For comparison
which as expected returns the same Ethereum address:
23ad59cc6afff2e508772f69d22b19ffebf579e7
23ad59cc6afff2e508772f69d22b19ffebf579e7
23ad59cc6afff2e508772f69d22b19ffebf579e7
One thing to note here is that Keys.getAddress(byte[]) does not pad the passed byte[], while the overloads for BigInteger or hex strings implicitly pad. This can be relevant e.g. when converting a BigInteger (e.g. provided by Sign.publicKeyFromPrivate(addrKey.getPrivKey())) to a byte[], since the result can also have less than 64 bytes (which would lead to different Keccak-256 hashes). If Keys.getAddress(byte[]) is used in this case, it must be explicitly padded with leading 0x00 values up to a length of 64 bytes.

How to make an audio RTP packet without using API along with the transmission and unpacking of the RTP packet

I'm new in VoIP. I was wondering to create an application that streams audio using Client/Server architecture using RTP. Different APIs are available but I need to get understanding at core level. I have studied RFC. Can anybody suggest me how to make an audio RTP packet and send it to the server along with the unpacking of the packet in JAVA.
Thanking in advance.
Create an empty Java class.
Add members for all the fields in the RTP header. Use bool for the single bit fields. For the numerical fields, you need to be mindful of how many bits you need, i.e. use int for SSRC, and timestamp, short for sequence, byte for payload type, etc. CSRC should be an array (or arrayList or whatever) of ints. Audio payload should be a byte array.
Packets are just arrays of bytes, so you need a ToBytes() method that will output a packet byte[], and a constructor that takes a byte[] as a parameter. To send a packet, call ToBytes() and put the result in a UDP packet.
In your ToBytes() method, create a byte array that's 12 bytes, plus an additional 4 bytes for each CSRC, plus however many bytes are in your audio payload.
Single bit values you need to set using the bitwise OR operator. For example, the Marker bit is the first bit of the second byte, so to set it:
if(marker)
{
bytes[1] = bytes[1] | 0x80; //0x80 is 1000 0000
}
To set the values that are ints or shorts, you'll need to convert the value to a network order (bigendian) byte array and then set it in the buffer using arraycopy. I'll leave it up to you to find out how to create the network order byte array.
For the constructor that takes a byte[], you'll need to do the above process in reverse. To check the value of a single bit, use the AND operator, e.g.:
marker = bytes[1] & 0x80 == 1;
Either in this class or a helper class you'll probably need methods to help set the timestamp based on the packet count and sample rate. For example, if the payload is G.711, it's 8000 samples/second, which means a packet sent every 20ms with a 160 byte payload, so timestamp will increase by 160 every packet.

How to use User Data in smpp?

How to use User Data(UDH) in smpp? Now I want to send sms specified port.
I use OpenSMPP as my project lib..
Follow these steps to send UDH over SMPP:
Set the UDHI bit to 1 on the esm_class field. The simplest way to do this - esm_class = esm_class | 0x40.
Put UDH at the beginning of short_message field. Read on for a quick summary. See the references to know in details how to encode UDH.
Here is how to encode UDH:
The first byte of UDH must mention the length (in bytes) of remaining part of UDH. Since you may not know this ahead, you may have to calculate it later on.
Then follows one or more IE (Information Element). Each IE has 3 parts:
First byte: IEI (IE Indicator). Identifies the element you want to encode. There are established IEI.
Second byte: IEIDL (IEI Data Length). Identifies the number of bytes that holds the data part. Each established IEI has fixed value for this field.
Third byte and rest part: IEID (IEI Data): Holds the data part. Each established IEI has fixed format of the data.
Count the total bytes consumed by each IE and put the result in the first byte.
For sending SMS to a part, you can use IEI 0x04 or 0x05. I have only seen 0x05 being used.
References
3GPP specification: 23.040
User Data Header

Can all tag numbers be extracted from a given protobuf serialization?

Given a protobuf serialization is it possible to get a list of all tag numbers that are in the message? Generally is it possible to view the structure of the message without the defining .proto files?
Most APIs will indeed have some form of reader-based API that allows you to enumerate a raw protobuf stream. However, that by itself is not enough to fully understand the data, since without the schema the interpretation is ambiguous:
a varint could be zig-zag encoded (sint32/sint64), or not (int32/int64/uint32/uint64) - radically changing the meaning, or a boolean, or an enum
a fixed-32/fixed-64 could be a signed or unsigned integer, or could be an IEEE754 float/double
a length-prefixed chunk could be a UTF-8 string, a BLOB, a sub-message, or a "packed" repeated set of primitives; if it is a sub-message, you'll have to repeat recursively
So... yes and no. Certainly you can get the field numbers of the outermost message.
Another approach would be to use the regular API against a type with no members (message Naked {}), and then query the unexpected data (i.e. all of it) via the "extension" API that many implementations provide.
You can get all the tag numbers which appear in one particular message, but you won't get any nested messages - and you won't know the types of those fields, only some subset of possible types.
If you look at the wire encoding, you can see that (for example) byte arrays, strings and nested messages are all encoded the same way - so you may know that "field 3 is a length-prefixed binary field" but you won't know whether that means it's a nested message, a string or a byte array.

How is this 13 bytes long?

Two quotes:
All of the remaining messages in the protocol take the form of <length prefix><message ID><payload>. The length prefix is a four byte big-endian value. The message ID is a single decimal byte. The payload is message dependent.
request: <len=0013><id=6><index><begin><length>
The request message is fixed length, and is used to request a block.
The payload contains the following information:
index: integer specifying the zero-based piece index
begin: integer specifying the zero-based byte offset within the piece
length: integer specifying the requested length.
When I write everything it sums up to 5 bytes. Using
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
byteStream.write( 13 );
byteStream.write( 6 );
byteStream.write( index );
byteStream.write( begin );
byteStream.write( length );
message = byteStream.toByteArray();
EDIT: Sorry i was kind of pissed when i wrote it. its the bittorent protocol.
Using this spec.
The write() method writes one byte.
If you send it a char or int it just strips everything above the 8th bit with & 0xFF.
You have more options with DataOutputStream (writeInt, writeShort etc.) but it uses big endian byte order so you might need to perform an Integer.reverseBytes() (or Short.reverseBytes()) call before passing in the value to the writeXYZ() method.
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(byteStream);
dout.writeInt( 0x13 ); // L:4
dout.write( 6 ); // L:5
dout.writeShort( index ); // guess, L:7
dout.writeLong( begin ); // >4GB support? L:15
dout.writeInt( length ); // clients accept below to 2^17, L:19
dout.flush(); // to be sure
message = byteStream.toByteArray();
Remark: The spec doesn't state the length of index, begin and length. I just wanted to give a sample of the available options.
Edit 2: Edited the sample based on D.Shawley's answer and a spec found here.
I'm not sure what you are getting at here... the quoted text doesn't say what the length of <index>, <begin>, or <length> is. The first quote states, rather clearly, that a message consists of a 4-byte length, followed by a 1-byte identifier, and an arbitrary payload.
The length of the payload is probably either the value specified as <length> or <length>+5 depending on exactly what <length> means. The second quote looks like the definition of whatever message is identified by the 1-byte identifier of 0x06. I would guess that:
the payload, the bytes that make up <index><begin><length>, is probably 14 bytes long
the length is being displayed in hex so 0x0013 is 19 decimal
In any case, the byte stream that you are generating does not seem to match the message definition AND the message definition lacks clarity.
write() writes bytes. 5 write()'s produces 5 bytes.
See write(int b).
Writes the specified byte to this
output stream. The general contract
for write is that one byte is written
to the output stream. The byte to be
written is the eight low-order bits of
the argument b. The 24 high-order bits
of b are ignored.
Subclasses of
OutputStream must provide an
implementation for this method.
Parameters:
b - the byte.

Categories

Resources