Question

I tried to use @RequestBody byte[] data as automatic Base64 decoder, in order to receive some RSA encrypted data and afterwards decrypt it in my service:

Controller:

@RequestMapping
void doIt(@RequestBody byte[] data) {
    service.doIt(data);
}

Service:

void doIt(byte[] encryptedData) {               
    String testDataString = "hgLGtzF4D8tlJbVivQgaXXwfI9TbQ//PrYHEez5k93sqJSi17eLCa+r/cGNGvoxDRaPYONvP4yxW0ajKDFrusQ4V4owfhkijS9KzBOTjBeAVmA+5jBsZCdoxwCA65DiP5lJ+GRbn8CjcjCr4DaEWFbWHsyvY4NGGAQLuYv+PyZipfU9pXTEDsBb15NwaHlD5m7Z4CHWdWTt1ARvRaQs56Bp63/IEmGR7w4brA1+iuKPv83FLh0rsxyoJ+F8TeqtuPhm2fHTh1FiHn0Bpaqqoyd/cBl0/utSzu4qoZhB3AiVgLjnT6Iy9p5nVoAozxQo/Es59LrpGZfjYJer073jNIg==";
    byte[] testDataBytes = Base64.decodeBase64(testDataString);

    System.out.println(encryptedData.length);
    System.out.println(testDataBytes.length);

    System.out.println(new String(encryptedData).length());
    System.out.println(Base64.encodeBase64String(testDataBytes).length());

    System.out.println(new String(encryptedData).equals(Base64.encodeBase64String(testDataBytes)));
}

Request:

Content-Type: application/octet-stream

Request Payload: 
hgLGtzF4D8tlJbVivQgaXXwfI9TbQ//PrYHEez5k93sqJSi17eLCa+r/cGNGvoxDRaPYONvP4yxW0ajKDFrusQ4V4owfhkijS9KzBOTjBeAVmA+5jBsZCdoxwCA65DiP5lJ+GRbn8CjcjCr4DaEWFbWHsyvY4NGGAQLuYv+PyZipfU9pXTEDsBb15NwaHlD5m7Z4CHWdWTt1ARvRaQs56Bp63/IEmGR7w4brA1+iuKPv83FLh0rsxyoJ+F8TeqtuPhm2fHTh1FiHn0Bpaqqoyd/cBl0/utSzu4qoZhB3AiVgLjnT6Iy9p5nVoAozxQo/Es59LrpGZfjYJer073jNIg==

The Output:

(Spring) Byte length:          344
(test)   Byte length:          256
(Spring) Base64 String length: 344
(test)   Base64 String length: 344
         Base64 String equals: true

As you can see:

  • The request contains exactly the same data as the test data I put into the source code.

  • After doing Base64 encoding both have the same length and are `equal``

  • BUT: The length of the byte arrays are different.

Question:

Why is the byte[] that was generated by Spring bigger? (It's useless when trying to decode it using some RSA private key, because RSA expects a length of 256.)

Workaround:

Controller:

@RequestMapping
void doIt(@RequestBody String data) {
    service.doIt(Base64.decodeBase64(data));
}
Was it helpful?

Solution

In Spring's ByteArrayHttpMessageConverter, you can find the method readInternal which converts the contents of a request into the desired format (in this case byte[]).

The code (Spring 4.0.0.RELEASE):

long contentLength = inputMessage.getHeaders().getContentLength();
ByteArrayOutputStream bos = new ByteArrayOutputStream(contentLength >= 0 ? (int) contentLength : StreamUtils.BUFFER_SIZE);
StreamUtils.copy(inputMessage.getBody(), bos);
return bos.toByteArray();

The second line says: *If the request payload isn't empty take it's content length, and set the capacity of the ByteArrayOutputStream with that. Else if the content length is < 0, then set it to StreamUtils.BUFFER_SIZE (= 4096).*

Im not really sure why it is implemented this way, but that's how it actually works.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top