Here is the Java code:
public static String sign(String data) throws Exception {
KeyPair keyPair = loadKeyPair(System.getProperty("user.dir"), "ECDSA");
Signature signature = Signature.getInstance("SHA256withECDSA", "BC");
signature.initSign(keyPair.getPrivate(), new SecureRandom());
byte[] message = data.getBytes();
signature.update(message);
byte[] sigBytes = signature.sign();
String signatureStr = new BigInteger(1, sigBytes).toString(16);
return signatureStr;
}
Then the C++ Code to verify signatures
bool VerifyMessage( const ECDSA<ECP, SHA256>::PublicKey& key, const string& message, const string& signature )
{
bool result = false;
// Hexa encoding version, more readable
std::string decodedSignature;
StringSource(signature, true,
new HexDecoder(
new StringSink(decodedSignature)));
StringSource(decodedSignature+message, true,
new SignatureVerificationFilter(ECDSA<ECP,SHA256>::Verifier(key),
new ArraySink((byte*)&result, sizeof(result))));
return result;
}
I was thinking that I need to encode my signature to hexa but it didn't resolve my problem. I've written a c++ version of the sign method using crypto++ and it's verified. so why when I use the java code, the signature is not verified. Thanks
... why when I use the java code, the signature is not verified?
OpenSSL and Java use an ASN.1/DER encoding for the signature, and Crypto++ uses IEEE P1363's format for the signature.
ASN.1: SEQUENCE ::= { r INTEGER, s INTEGER }
P1363: [byte array r][byte array s]
You need to convert between the formats. Crypto++ provides DSAConvertSignatureFormat to convert between formats. There is an example on the Crypto++ wiki at Elliptic Curve Digital Signature Algorithm | OpenSSL and Java Interop.
Here is the Crypto++ code from the wiki. It uses OpenSSL and its command line tools rather than Java. There is no material difference because OpenSSL and Java output signatures in ASN.1/DER format.
#include "cryptlib.h"
#include "eccrypto.h"
#include "files.h"
#include "dsa.h"
#include "sha.h"
#include "hex.h"
#include <iostream>
using namespace CryptoPP;
int main(int argc, char* argv[])
{
// Load DER encoded public key
FileSource pubKey("secp256k1-pub.der", true /*binary*/);
ECDSA<ECP, SHA1>::Verifier verifier(pubKey);
// Java or OpenSSL created signature. It is ANS.1
// SEQUENCE ::= { r INTEGER, s INTEGER }.
const byte derSignature[] = {
0x30, 0x44, 0x02, 0x20, 0x08, 0x66, 0xc8, 0xf1,
0x6f, 0x15, 0x00, 0x40, 0x8a, 0xe2, 0x1b, 0x40,
0x56, 0x28, 0x9c, 0x17, 0x8b, 0xca, 0x64, 0x99,
0x37, 0xdc, 0x35, 0xad, 0xad, 0x60, 0x18, 0x4d,
0x63, 0xcf, 0x4a, 0x06, 0x02, 0x20, 0x78, 0x4c,
0xb7, 0x0b, 0xa3, 0xff, 0x4f, 0xce, 0xd3, 0x01,
0x27, 0x5c, 0x6c, 0xed, 0x06, 0xf0, 0xd7, 0x63,
0x6d, 0xc6, 0xbe, 0x06, 0x59, 0xe8, 0xc3, 0xa5,
0xce, 0x8a, 0xf1, 0xde, 0x01, 0xd5
};
// P1363 'r || s' concatenation. The size is 32+32 due to field
// size for r and s in secp-256. It is not 20+20 due to SHA-1.
SecByteBlock signature(verifier.SignatureLength());
DSAConvertSignatureFormat(signature, signature.size(), DSA_P1363,
derSignature, sizeof(derSignature), DSA_DER);
// Message "Attack at dawn!"
const byte message[] = {
0x41, 0x74, 0x74, 0x61, 0x63, 0x6b, 0x20, 0x61,
0x74, 0x20, 0x64, 0x61, 0x77, 0x6e, 0x21, 0x0a
};
// https://www.cryptopp.com/wiki/Elliptic_Curve_Digital_Signature_Algorithm
bool result = verifier.VerifyMessage(message, sizeof(message), signature, signature.size());
if (result)
std::cout << "Verified message" << std::endl;
else
std::cout << "Failed to verify message" << std::endl;
return 0;
}
And here is the result of running the test program.
$ ./test.exe
Signature (64):
0866C8F16F1500408AE21B4056289C178BCA649937DC35ADAD60184D63CF4A06784CB70BA3FF4FCE
D301275C6CED06F0D7636DC6BE0659E8C3A5CE8AF1DE01D5
Verified message
Here is the setup I used to reproduce cat test.txt | openssl dgst -ecdsa-with-SHA1 -sign sample.key -keyform DER > test.sig. It is from #DivB's question at ECDSA sign with OpenSSL, verify with Crypto++.
$ cat test.txt
Attack at dawn!
$ hexdump -C test.txt
00000000 41 74 74 61 63 6b 20 61 74 20 64 61 77 6e 21 0a |Attack at dawn!.|
00000010
# Create private key in PEM format
$ openssl ecparam -name secp256k1 -genkey -noout -out secp256k1-key.pem
$ cat secp256k1-key.pem
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIO0D5Rjmes/91Nb3dHY9dxmbM7gVfxmB2+OVuLmWMbGXoAcGBSuBBAAK
oUQDQgAEgVNEuirUNCEVdf7nLSBUgU1GXLrtIBeglIbK54s91HlWKOKjk4CkJ3/B
wGAfcYKa+DgJ2IUQSD15K1T/ghM9eQ==
-----END EC PRIVATE KEY-----
# Convert private key to ASN.1/DER format
$ openssl ec -in secp256k1-key.pem -inform PEM -out secp256k1-key.der -outform DER
$ dumpasn1 secp256k1-key.der
0 116: SEQUENCE {
2 1: INTEGER 1
5 32: OCTET STRING
: ED 03 E5 18 E6 7A CF FD D4 D6 F7 74 76 3D 77 19
: 9B 33 B8 15 7F 19 81 DB E3 95 B8 B9 96 31 B1 97
39 7: [0] {
41 5: OBJECT IDENTIFIER secp256k1 (1 3 132 0 10)
: }
48 68: [1] {
50 66: BIT STRING
: 04 81 53 44 BA 2A D4 34 21 15 75 FE E7 2D 20 54
: 81 4D 46 5C BA ED 20 17 A0 94 86 CA E7 8B 3D D4
: 79 56 28 E2 A3 93 80 A4 27 7F C1 C0 60 1F 71 82
: 9A F8 38 09 D8 85 10 48 3D 79 2B 54 FF 82 13 3D
: 79
: }
: }
# Create public key from private key
$ openssl ec -in secp256k1-key.der -inform DER -pubout -out secp256k1-pub.der -outform DER
$ dumpasn1 secp256k1-pub.der
0 86: SEQUENCE {
2 16: SEQUENCE {
4 7: OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
13 5: OBJECT IDENTIFIER secp256k1 (1 3 132 0 10)
: }
20 66: BIT STRING
: 04 81 53 44 BA 2A D4 34 21 15 75 FE E7 2D 20 54
: 81 4D 46 5C BA ED 20 17 A0 94 86 CA E7 8B 3D D4
: 79 56 28 E2 A3 93 80 A4 27 7F C1 C0 60 1F 71 82
: 9A F8 38 09 D8 85 10 48 3D 79 2B 54 FF 82 13 3D
: 79
: }
# Sign the message using the private key
$ cat test.txt | openssl dgst -ecdsa-with-SHA1 -sign secp256k1-key.der -keyform DER > test.sig
# Dump the signature as hex
$ hexdump -C test.sig
00000000 30 44 02 20 08 66 c8 f1 6f 15 00 40 8a e2 1b 40 |0D. .f..o..#...#|
00000010 56 28 9c 17 8b ca 64 99 37 dc 35 ad ad 60 18 4d |V(....d.7.5..`.M|
00000020 63 cf 4a 06 02 20 78 4c b7 0b a3 ff 4f ce d3 01 |c.J.. xL....O...|
00000030 27 5c 6c ed 06 f0 d7 63 6d c6 be 06 59 e8 c3 a5 |'\l....cm...Y...|
00000040 ce 8a f1 de 01 d5 |......|
00000046
# Dump the signature as ASN.1/DER
$ dumpasn1 test.sig
0 68: SEQUENCE {
2 32: INTEGER
: 08 66 C8 F1 6F 15 00 40 8A E2 1B 40 56 28 9C 17
: 8B CA 64 99 37 DC 35 AD AD 60 18 4D 63 CF 4A 06
36 32: INTEGER
: 78 4C B7 0B A3 FF 4F CE D3 01 27 5C 6C ED 06 F0
: D7 63 6D C6 BE 06 59 E8 C3 A5 CE 8A F1 DE 01 D5
: }
By the way, another way around your problem (especially allowing you to avoid the command line) would be to modify the Java code in order to have a way to produce the R and S values, as well as to reproduce the DER encoded values.
For example you can extract the R and S values from the Java signature using those:
public static BigInteger extractR(byte[] signature) throws Exception {
int startR = (signature[1] & 0x80) != 0 ? 3 : 2;
int lengthR = signature[startR + 1];
return new BigInteger(Arrays.copyOfRange(signature, startR + 2, startR + 2 + lengthR));
}
public static BigInteger extractS(byte[] signature) throws Exception {
int startR = (signature[1] & 0x80) != 0 ? 3 : 2;
int lengthR = signature[startR + 1];
int startS = startR + 2 + lengthR;
int lengthS = signature[startS + 1];
return new BigInteger(Arrays.copyOfRange(signature, startS + 2, startS + 2 + lengthS));
}
These methods are notably used in Wycheproof to play around with the BigIntegers directly.
These can allow you to reconstruct the P1363 encoding used by CryptoPP in Java, but be careful not to forget the left padding with 0s of the bytearrays. (Otherwise you may have problems when the R or S bytearray is smaller than the expected length.)
And you can also reconstruct the DER encoded signature from big integers using:
public static byte[] derSign(BigInteger r, BigInteger s) throws Exception {
byte[] rb = r.toByteArray();
byte[] sb = s.toByteArray();
int off = (2 + 2) + rb.length;
int tot = off + (2 - 2) + sb.length;
byte[] der = new byte[tot + 2];
der[0] = 0x30;
der[1] = (byte) (tot & 0xff);
der[2 + 0] = 0x02;
der[2 + 1] = (byte) (rb.length & 0xff);
System.arraycopy(rb, 0, der, 2 + 2, rb.length);
der[off + 0] = 0x02;
der[off + 1] = (byte) (sb.length & 0xff);
System.arraycopy(sb, 0, der, off + 2, sb.length);
return der;
}
As you can see, these methods might be translated into C++ code, since they are really basic byte manipulations, but that's another story ;)
Building on top of Lery's excellent answer, I found myself wanting a 64-byte fixed P1363 style signature. The Java solution posted is great, but the r and s values may contain sign bits and therefore result in a 64-66 bytes signature.
In this Kotlin function, I compute the r and s values, and I take only the lower 32 bytes each, and this gave me the 64-byte signature I wanted.
fun generateSignatureFromKeystore(message: ByteArray, privateKey: PrivateKey): ByteArray {
// BouncyCastle's signing doesn't work with Android Keystore's ECPrivateKey
val signatureConfig = Signature.getInstance("SHA256withECDSA").apply {
initSign(privateKey)
update(message)
}
val signature = signatureConfig.sign()
// Convert ASN.1 DER signature to IEEE P1363
val startR = if (signature[1].toUnsignedInt().and(0) != 0) 3 else 2
val lengthR = signature[startR + 1].toUnsignedInt()
val r = signature.copyOfRange(startR + 2, startR + 2 + lengthR).takeLast(32).toByteArray()
val startS = startR + 2 + lengthR
val lengthS = signature[startS + 1].toInt()
val s = signature.copyOfRange(startS + 2, startS + 2 + lengthS).takeLast(32).toByteArray()
return r + s
}
private fun Byte.toUnsignedInt(): Int = toInt().and(0xFF)
There is a stream of data which is sent from server. I need to store this byte stream into a file. The problem is the data which I output to console and the one which I store in a file are different. Seems like there is a change in format of data when I stored in a file.
Here is the program:
try
{
System.out.println("My Address is "+serverSocket.getLocalSocketAddress());
Socket server = serverSocket.accept(); // return a new socket
System.out.println("Connected to client "+server.getRemoteSocketAddress());
inputStream = server.getInputStream();
in = new DataInputStream(inputStream);
out = new FileOutputStream("output.txt");
ArrayList<Byte> bytes = new ArrayList<Byte>();
int curi;
byte cur;
byte[] curBytes = null;
int length = 0;
System.out.println("Before while loop");
while((curi = in.read())!=-1 && count!=500)
{
System.out.println(count+" Reading some data");
//out.write(curi);
cur = (byte)curi;
bytes.add(cur);
curBytes = getPrimativeArray(bytes);
String curBytesString = new String(curBytes, "UTF-8");
count++;
}
int i=0;
for(byte b : bytes)
{
System.out.print(b+" ");
curBytes[i] = b;
i++;
}
out.write(curBytes);
server.close();
}
catch(IOException e)
{
e.printStackTrace();
}
What I print using System.out.print(b+" "); and the one I store in curBytes[] are the same thing. But when I compare the console and file output, they are different.
Console output: 0 0 113 -100 -126 -54 0 32 14 1 0 0 1 -58 60 54 0 3 63 -2 85 74 -81 -88 0 9 1 24 85 74 -81 -48 0 13 65 -113 85 74 -81 -88 0 12 125 -126 85 74 -81 -88 0 13 21 97 85 74 -81 -88 0 13 31 19 85 74 -81 -48 0 13 42 24 0 6 0 0 0 0 0 0 0 0 0 0 32 0 7 -100 0 -5 6 -128 0 -56 29 -127 23 112 -1 -1 0 0 64 0 1 -121 28 115 105 112 58 43 49 52 50 50 50 48 57 57 57 49 53 64 111 110 101 46 97 116 116 46 110 101 116 28 115 105 112 58 43 49 52 50 50 50 48 57 57 57 54 53 64 111 110 101 46 97 116 116 46 110 101 116 37 50 57 54 53 45 49 53 48 53 48 54 50 51 50 55 48 50 45 50 48 53 48 54 54 50 55 54 54 64 48 48 55 56 48 48 49 49 16 32 1 5 6 64 0 0 0 32 16 0 0 0 120 0 17 16 32 1 24 -112 16 1 46 2 0 0 0 0 0 0 0 6 1 -113 0 4 0 33 -64 -42 0 91 5 8 0 9 0 -56 0 0 0 15 3 85 74 -81 -88 0 12 -120 -28 8 0 9 0 -56 0 0 0 15 3 85 74 -81 -88 0 12 -44 -39 8 0 4 0 -56 0 0 1 11 3 85 74 -81 -88 0 9 1 24 8 0 5 0 0 0 0 0 0 3 85 74 -81 -88 0 13 31 19 8 0 1 0 -56 0 0 0 6 3 85 74 -81 -48 0 13 42 24 -64 34 4 24 9 89 83 73 80 47 50 46 48 47 84 67 80 32 91 50 48 48 49 58 53 48 54 58 52 48 48 48 58 48 58 50 48 49 48 58 48 58 55 56 58 49 49 93 58 49 51 55 48 59 98 114 97 110 99 104 61 122 57 104 71 52 98 75 50 57 48 45 48 48 55 56 48 48 49 49 45 48 48 48 102 45 52 52 49 57 55 49 52 48 51 3 85 74 -81 -88 0 12 -120 -28 127 83 73 80 47 50 46 48 47 84 67 80 32 91 50 48 48 49 58 53 48 54 58 52 48 48 48 58 48 58 50 48 49 48 58 48 58 55 56 58 49 49 93 58 49 51 55 48 59 114 101 99 101 105 118 101 100 61 50 48 48 49
File Output: ^#^#q<9c><82>Ê^# ^N^A^#^#^AÆ<6^#^C?þUJ¯¨^# ^A^XUJ¯Ð^#^MA<8f>UJ¯¨^#^L}<82>UJ¯¨^#^M^UaUJ¯¨^#^M^_^SUJ¯Ð^#^M*^X^#^F^#^#^#^#^#^#^#^#^#^# ^#^G<9c>^#û^F<80>^#È^]<81>^Wpÿÿ^#^##^#^A<87>^\sip:+14222099915#one.att.net^\sip:+14222099965#one.att.net%2965-150506232702-2050662766#00780011^P ^A^E^F#^#^#^# ^P^#^#^#x^#^Q^P ^A^X<90>^P^A.^B^#^#^#^#^#^#^#^F^A<8f>^#^D^#!ÀÖ^#[^E^H^# ^#È^#^#^#^O^CUJ¯¨^#^L<88>ä^H^# ^#È^#^#^#^O^CUJ¯¨^#^LÔÙ^H^#^D^#È^#^#^A^K^CUJ¯¨^# ^A^X^H^#^E^#^#^#^#^#^#^CUJ¯¨^#^M^_^S^H^#^A^#È^#^#^#^F^CUJ¯Ð^#^M*^XÀ"^D^X YSIP/2.0/TCP [2001:506:4000:0:2010:0:78:11]:1370;branch=z9hG4bK290-00780011-000f-441971403^CUJ¯¨^#^L<88>ä^?SIP/2.0/TCP [2001:506:4000:0:2010:0:78:11]:1370;received=2001
Please let me know at what step I'm making a mistake.
The other answers here tell you to use a PrintWriter or a FileWriter instead of the FileOutputStream but I'm fairly sure that this is not what you want.
Your problem is that you're writing raw bytes to a file and then reading it back as characters and comparing that to byte values represented as characters and then printed with System.out.
Let's take a look at what happens when you print a byte with the value 65 (or 01000001 in binary).
When you use System.out.print you will invoke PrintStream.print(int) with the integer value of 65 which will in turn print the characters 6 and 5 to the terminal.
When you use out.write you will invoke FileOutputStream.write(byte[]) which will write the bits 01000001 to the file.
Later, when you check the contents of the file your tool will try to interpret this byte as a character and it will most likely use the ASCII encoding to do so (even if you're using Unicode as your default encoding this is likely what will happen since Unicode is a superset of ASCII). This results in the character A being printed.
If you want to view the output file in a way similar to what you've printed with System.out.print you can use the following command on linux:
$ hexdump -e '/1 "%i "' <file>
Example:
$ cat /etc/issue
Ubuntu 12.04.5 LTS \n \l
$ hexdump -e '/1 "%i "' /etc/issue
85 98 117 110 116 117 32 49 50 46 48 52 46 53 32 76 84 83 32 92 110 32
92 108 10 *
My first answer was wrong, so I am editing this because I made the assumption that you could write out a string to the FileOutputStream, but I don't think that is the case. FileOutputStream is only used for byte streams, so you've got to stick to that format when writing out to the file.
If you hold the data in a buffer[array], and then write those bytes out to a file that you have created using the output stream, it should work. I found this document that might be helpful.
The main idea is that somewhere in your code, the byte array isn't getting written to the file correctly. Perhaps its just a matter of adding the close() method.
out.close();
server.close();
reading and writing files in java
Here is the section I found useful.
import java.io.*;
public class Test {
public static void main(String [] args) {
// The name of the file to create.
String fileName = "temp.txt";
try {
// Put some bytes in a buffer so we can
// write them. Usually this would be
// image data or something. Or it might
// be unicode text.
String bytes = "Hello theren";
byte[] buffer = bytes.getBytes();
FileOutputStream outputStream =
new FileOutputStream(fileName);
// write() writes as many bytes from the buffer
// as the length of the buffer. You can also
// use
// write(buffer, offset, length)
// if you want to write a specific number of
// bytes, or only part of the buffer.
outputStream.write(buffer);
// Always close files.
outputStream.close();
System.out.println("Wrote " + buffer.length +
" bytes");
}
catch(IOException ex) {
System.out.println(
"Error writing file '"
+ fileName + "'");
// Or we could just do this:
// ex.printStackTrace();
}
}
}
The console (System.out) is a PrintWriter, while the file output is a FileOutputStream.
The basic difference between Stream and Writer: Streams are supposed to manipulate "raw data", like numbers taken directly from binary format, while writers are used to manipulate "human-readable data", transforming all the data you write.
For example, the 6 int is different from the 6 character. When you use a stream, you write directly the int, while with a writer, the data wrriten is transformed into the character.
Then, if you want your file output to be the same as your console output, do not use FileOutputStream, but instead, use FileWriter, and it's method write(String).
How to make this work:
1 - replace out = new FileOutputStream("output.txt"); by out = new FileWriter("output.txt");
2 - replace out.write(curBytes); by:
for (byte b : curBytes) {
out.write(b + " ");
}
I would suggest you use IOUtils.copy and use a BufferedReader
to wrap your InputStream.
The output stream should obviously be FileOutputStream
I hope this helps
I am trying to read a file that is under MF. The EF.DIR file. I got the file's SFID, so I don't use the method SELEC_FILE first (since it's not necessary).
I might be having some problems with understanding the P2 parameter (the OFFSET). I read couple of explanations, but still don't get what OFFSET do they mean. But I tried all the numbers from 0-8 just in case, none worked.
CLA = 0x00
INS_READ = 0xB0
P1_READ = 0x9E (by the datasheed: bit(8) = 1, bit(7:6) = 00, bit(5:1): SFID)
P2 = 0x04 (I figured that the offset should be from bit0 to bit4 (the SFID)
Le = 0 (by the datasheet I have, this should mean that any size will be returned)
This is my code:
byte[] readBinary = { CLA, INS_READ, P1_READ, (byte) 0x04, (short) 0};
ResponseAPDU read = channel.transmit(new CommandAPDU(readBinary));
String responseReadToString =read.toString();
System.out.println("Response Read: " + responseReadToString + "\n" + "Response Read (HEX): " + responseReadHex );
The output I get in Console is:
Response Read: ResponseAPDU: 2 bytes, SW=6b00
Response Read (HEX): 6B00
Explanations of SW1-SW2 for 6B00:
Incorrect parameters P1-P2
I really don't know what is wrong and it's really hard to find support on SmartCards online, so hopefully someone who knows this better can help me out. I also tried with using SELECT_FILE first and the use READ_BINARY after it (without the SFID in P1 parametr ofcourse), but it responded with "No EF is set as current".
Any help guys?
The offset is the position/startpoint from where you start reading.
Example: Data = [0x00 0x01 0x02 0x03 0x04 0x05]
When you query a ReadBinary with offset=2 then returned data will be [0x02 0x03 0x4 0x05]
As you probably want to read the whole EF.DIR file offset shall be zero.
For reading EF.DIR you can either send
00 B0 9E 00 00
or
00 B1 2F 00 04 54 02 00 00 00
or
00 A4 02 0C 02 2F 00
00 B0 00 00 00
I have a java nio socket server that needs to communicate with a C socket client. The C socket client sends data to the server with ASCII codes above 127, using one byte per ASCII code. The server needs to send back the same.
I need to convert a string into a byte array with the same length (one byte per code).
The string is like 1200üö001001001, where it contains some ascii codes above 127.
In the research I did, I did not find a solution. I tried this
byte[] b = "1200üö001001001".getBytes("UTF-8");
byte[] b = "1200üö001001001".getBytes("US-ASCII");
byte[] b = "1200üö001001001".getBytes("ISO-8859-1");
byte[] b = "1200üö001001001".getBytes();
Some of these convert üö into ?? or multiple bytes per ASCII code, causing a different length between byte array and string.
I needing some help.
This is an example of data that comes from the C socket client. dots are ascii codes from Client.
<code>
0000 00 ff 31 32 30 30 fc f6 00 01 08 e1 e0 00 00 00 ..1200..........
0010 00 00 14 00 00 00 31 36 34 36 30 30 32 38 30 30 ......1646002800
0020 30 30 30 30 30 34 31 38 30 31 32 30 30 30 30 30 0000041801200000
0030 30 30 30 30 30 30 31 30 30 30 30 30 30 30 30 30 0000001000000000
0040 30 30 31 30 30 30 30 30 30 30 30 30 30 30 31 30 0010000000000010
0050 30 30 36 31 30 30 30 30 30 30 36 31 30 30 30 30 0061000000610000
0060 30 30 35 31 35 39 31 31 31 34 30 39 32 33 31 33 0051591114092313
0070 32 31 31 32 33 32 30 35 31 34 30 39 32 33 30 36 2112320514092306
0080 39 39 39 39 39 39 30 30 30 30 30 35 35 31 35 39 9999990000055159
0090 31 31 33 32 39 38 20 20 20 20 33 38 38 33 33 38 113298 388338
00a0 38 33 20 20 20 20 20 20 20 42 41 43 20 50 41 4e 83 XXX PAN
00b0 41 4d 41 20 54 45 53 54 3e 48 4f 57 41 52 44 20 AMA TEST>HOWARD
00c0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 50 P
00d0 41 30 32 33 30 30 31 30 30 31 31 30 30 32 30 30 A023001001100200
00e0 33 37 30 30 30 32 35 30 30 31 31 38 34 30 38 34 3700025001184084
00f0 30 38 34 30 30 30 30 39 31 31 30 30 30 30 30 30 0840000911000000
0100 31
This is the code i use to convert from hex string to byte array
line 4 i convert from binary eg. 1101 to equvalent hex string eg `3F`
line 13 i take the bitmap in hex string eg. `"fcf6000108e1e0000000000014000000"`
that contains 32 chars and try to convert to 16 bytes, but this results in 20 bytes
because some chars takes more than one byte
1 // Set bitmaps
2 if ( String.copyValueOf(zeros).indexOf("1", 64) == -1 ) { zeros[0] = '0'; }
3 tmp = String.copyValueOf(zeros);
4 bits = binToHex(tmp);
5
6 // check bits to send
7 if ( zeros[0] == '0') {
8 bits = bits.substring(0, 16);
9 }
10
11 // join message
12 tmp = sb.toString();
13 trm = isoCode + hexToASCII(bits) + tmp.substring(39);
14 System.out.println("Trama respuesta " + (new Timestamp((new Date()).getTime())).toString() + " " + trm);
// here the code to send back the message from nio socet to client
line mark with 100 add 2 space because there is a header with a short value that have the length of
the message to be readed by socket client
byte[] bytes = message.getBytes("ISO-8859-1");
writeLength = message.length();
//writeLength = bytes.length;
100 writeBuffer = ByteBuffer.allocate(writeLength + 2);
writeBuffer.putShort( (short)writeLength );
writeBuffer.put(message.getBytes()); // Para test
//this.writeBuffer.putChar('\n');
writeBuffer.flip();
// auxiliar methods
public String hexToASCII(String hex){
if(hex.length()%2 != 0){
System.err.println("requires EVEN number of chars");
return null;
}
StringBuilder sb = new StringBuilder();
//Convert Hex 0232343536AB into two characters stream.
for( int i=0; i < hex.length()-1; i+=2 ){
/*
* Grab the hex in pairs
*/
String output = hex.substring(i, (i + 2));
/*
* Convert Hex to Decimal
*/
int decimal = Integer.parseInt(output, 16);
sb.append((char)decimal);
}
return sb.toString();
}
private final String HEXES = "0123456789ABCDEF";
private final String HEX[] = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
private final String BIN[] = {"0000","0001","0010","0011","0100","0101","0110","0111","1000","1001","1010","1011","1100","1101","1110","1111"};
/*
* Convert binary to hex string
*/
public String binToHex(String bin) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < bin.length()-1 ; i += 4) {
sb.append(HEX[ArrayUtils.indexOf(BIN, bin.substring(i, (i + 4)))]);
}
return sb.toString();
}
You are mixing bytes and characters. There are dozens of ways to encode characters like ü and ö into bytes and different encodings take different amount of bytes per character.
DO NOT try to convert binary stream to string unless you know that the bytes represent textual information AND you know which encoding was used to convert the text into bytes in the first place. If the data is not a text string, DO NOT try to interpret it as a text string and just wish that every byte maps to something reasonable.
You can work directly with byte arrays or use e.g. java.nio.ByteBuffer. If there is a text string amongst the data, you can separately convert the peticular bytes into strings.
Your binary bitmap is getting mangled by character encoding conversions. There is no point in doing it that way. You can just convert from hex to byte[].
This code suggests the way:
String bitmapHex = "00112233445566778899aabbccddeeff";
String isoCode = "1200";
String data = "313030303030303031 and more";
byte[] bitmap = javax.xml.bind.DatatypeConverter.parseHexBinary(bitmapHex);
int datagramLength = 2 + isoCode.length() + bitmap.length + data.length();
ByteBuffer buffer = ByteBuffer.allocate(datagramLength);
buffer.order(ByteOrder.BIG_ENDIAN).putShort((short)datagramLength);
buffer.put(isoCode.getBytes(encodingName));
buffer.put(bitmap);
buffer.put(data.getBytes(encodingName));
byte[] output = buffer.array();
Hi I am working on application where I have to read live packets
from network work on it. And display it in sophisticated way.
But problem is I have packet but it is in text file, so to open it
by Wireshark I have to convert it in .pcap format.
So how can I convert packet in text to pcap format.
My text file format is like this shown below,
Frame:
Frame: number = 0
Frame: timestamp = 2014-02-13 09:39:11.288
Frame: wire length = 174 bytes
Frame: captured length = 174 bytes
Frame:
Eth: ******* Ethernet - "Ethernet" - offset=0 (0x0) length=14
Eth:
Eth: destination = 01:00:5e:7f:ff:fa
Eth: .... ..0. .... .... = [0] LG bit
Eth: .... ...0 .... .... = [0] IG bit
Eth: source = ec:9a:74:4d:8e:03
Eth: .... ..0. .... .... = [0] LG bit
Eth: .... ...0 .... .... = [0] IG bit
Eth: type = 0x800 (2048) [ip version 4]
Eth:
Ip: ******* Ip4 - "ip version 4" - offset=14 (0xE) length=20 protocol suite=NETWORK
Ip:
Ip: version = 4
Ip: hlen = 5 [5 * 4 = 20 bytes, No Ip Options]
Ip: diffserv = 0x0 (0)
Ip: 0000 00.. = [0] code point: not set
Ip: .... ..0. = [0] ECN bit: not set
Ip: .... ...0 = [0] ECE bit: not set
Ip: length = 160
Ip: id = 0x4CD1 (19665)
Ip: flags = 0x0 (0)
Ip: 0.. = [0] reserved
Ip: .0. = [0] DF: do not fragment: not set
Ip: ..0 = [0] MF: more fragments: not set
Ip: offset = 0
Ip: ttl = 0 [time to live]
Ip: type = 17 [next: User Datagram]
Ip: checksum = 0xB0AA (45226) [correct]
Ip: source = 124.125.80.90
Ip: destination = 239.255.255.250
Ip:
Udp: ******* Udp offset=34 (0x22) length=8
Udp:
Udp: source = 58845
Udp: destination = 1900
Udp: length = 140
Udp: checksum = 0x5154 (20820) [correct]
Udp:
Data: ******* Payload offset=42 (0x2A) length=132
Data:
002a: 4d 2d 53 45 41 52 43 48 20 2a 20 48 54 54 50 2f M-SEARCH * HTTP/
003a: 31 2e 31 0d 0a 48 6f 73 74 3a 32 33 39 2e 32 35 1.1..Host:239.25
004a: 35 2e 32 35 35 2e 32 35 30 3a 31 39 30 30 0d 0a 5.255.250:1900..
005a: 53 54 3a 75 72 6e 3a 73 63 68 65 6d 61 73 2d 75 ST:urn:schemas-u
006a: 70 6e 70 2d 6f 72 67 3a 64 65 76 69 63 65 3a 57 pnp-org:device:W
007a: 41 4e 43 6f 6e 6e 65 63 74 69 6f 6e 44 65 76 69 ANConnectionDevi
008a: 63 65 3a 31 0d 0a 4d 61 6e 3a 22 73 73 64 70 3a ce:1..Man:"ssdp:
009a: 64 69 73 63 6f 76 65 72 22 0d 0a 4d 58 3a 33 0d discover"..MX:3.
00aa: 0a 0d 0a 00
Wireshark provides a command line pcap converter for Text Files:
https://www.wireshark.org/docs/man-pages/text2pcap.html
AutoHotkey solution:
; Change appropriate file locations
Run, %A_ProgramFiles%\ethereal\text2pcap.exe c:\test.txt c:\testconv.cap,%A_ProgramFiles%\ethereal
If you want to do a fully automated solution you can modify this function which actively watches a directory for file changes/creation.
http://www.autohotkey.com/board/topic/41653-watchdirectory/
If you have raw packets captured you can write them directly to pcap file format (see man 5 pcap-savefile) or use hexdump/xxd+text2pcap utility as ahkcoder recommends. Text2pcap also supports generation of dummy L2-4 headers (ethernet, ip, tcp/udp/sctp).
If you have only text representation, you can either reconstruct packet from it (so, generate all appropriate headers for each protocol used in your system) or adjust hex dump part offsets (to begin from 0000) and feed it to text2pcap.