Потерянные байты во входном потоке? - PullRequest
0 голосов
/ 07 мая 2018

Я пишу программу, в которой я посылаю байты ключа из пары ключей, которую я создал, через выходной сокет и использую их для воссоздания ключа на другой стороне. Сервер:

    KeyPairGenerator dsaKeyPairGenerator = 
    KeyPairGenerator.getInstance("DSA");
    dsaKeyPairGenerator.initialize(1024);
    KeyPair dsakeyPair = dsaKeyPairGenerator.generateKeyPair();
    PrivateKey dsaPrivate = dsakeyPair.getPrivate();
    PublicKey dsaPublic = dsakeyPair.getPublic();
    byte[] dsaPublicbytes = dsaPublic.getEncoded();
    clientSocket.getOutputStream().write(dsaPublicbytes.length);
    clientSocket.getOutputStream().write(dsaPublicbytes);

Клиент:

    int dsalength = clientSocket.getInputStream().read();
    byte[] dsaPublicbytes = new byte[dsalength];
    clientSocket.getInputStream().read(dsaPublicbytes);
    X509EncodedKeySpec dsaspec = new X509EncodedKeySpec(dsaPublicbytes);
    KeyFactory dsakeyFactory = KeyFactory.getInstance("DSA");
    PublicKey dsaKey = dsakeyFactory.generatePublic(dsaspec);

Однако в этой строке я получаю сообщение об ошибке:

    PublicKey dsaKey = dsakeyFactory.generatePublic(dsaspec);

Трассировка самой ошибки:

Exception in thread "main" java.security.spec.InvalidKeySpecException: Inappropriate key specification: IOException: Detect premature EOF
at sun.security.provider.DSAKeyFactory.engineGeneratePublic(DSAKeyFactory.java:119)
at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
at Client.main(Client.java:36)

Я исследовал и увидел, что EOF происходит, потому что не хватает байтов для создания ключа, что заставляет меня поверить, что это проблема с тем, как я посылаю байты. Я неправильно отправляю байты?

Ответы [ 2 ]

0 голосов
/ 07 мая 2018

Потерянные байты во входном потоке

Непрочитано байтов во входном потоке. Вы предполагали, что read() заполнил буфер. Это не обязано делать это. Используйте DataInputStream.readFully().

Вы также ограничиваете себя 128 байтами ключа, используя write(int) и read() без параметров, для отправки / получения длинного слова. Для этого используйте DataOutputStream.writeInt() и DataInputStream.readInt().

0 голосов
/ 07 мая 2018

Если предположить, что ваш первый байт не отправляет размер байтового массива ключа или вы используете ключ, размер которого больше 256-битного, то массив будет неполным. Попробуйте использовать методы DataOutputStream метода writeLong () или writeInt () для отправки байтового размера для инициализации массива правильного размера. Во-вторых, попробуйте использовать буферы для чтения при отправке.

Вот немного моего кода от моего файлового отправителя: Это отправляющая часть:

    OutputStream os = sock.getOutputStream();
    DataOutputStream dos = new DataOutputStream(os);     
    dos.writeInt(mybytearray.length);   
    dos.write(mybytearray, 0, mybytearray.length);   

Это часть получения:

InputStream in = sock.getInputStream();
DataInputStream dis = new DataInputStream(in);
int byteSize = clientData.readInt();
byte[] byteData = new Byte[byteSize];
dis.read(byteData);

Вы можете буферизовать принимающую часть, сообщая, сколько байтов нужно прочитать, используя метод DIS read(byte[],int,int), пока все байты не будут прочитаны. Я тестировал свой код на той же машине с очень маленькими данными, поэтому стабильность соединения не была фактором.

...