In Java, byte arrays are often used to transmit raw binary data as well as character-encoded data. Attempts to read raw binary data as if it were character-encoded data often fail because some of the bytes fall outside the default or specified encoding scheme and for that reason fail to denote valid characters. For example, converting a cryptographic key containing nonrepresentable bytes to character-encoded data for transmission may result in an error.
Noncompliant Code Example
This noncompliant code example attempts to convert the byte array representing a BigInteger
into a String
. Because some of the bytes do not denote valid characters, the resulting String
representation loses information. Converting the String
back to a BigInteger
produces a different value.
BigInteger x = new BigInteger("530500452766"); // convert x to a String byte[] byteArray = x.toByteArray(); String s = new String(byteArray); // convert s back to a BigInteger byteArray = s.getBytes(); x = new BigInteger(byteArray);
When this program was run on a Linux platform where the default character encoding is US-ASCII
, the string s
got the value {?J??
, because some of the characters were unprintable. When converted back to a BigInteger
, x
got the value 149830058370101340468658109
.
Compliant Solution
This compliant solution first produces a String
representation of the BigInteger
object and then converts the String
object to a byte array. This process is reversed on input. Because the textual representation in the String
object was generated by the BigInteger
class, it contains valid characters.
BigInteger x = new BigInteger("530500452766"); String s = x.toString(); // valid character data try { byte[] byteArray = s.getBytes("UTF8"); // ns prints as "530500452766" String ns = new String(byteArray, "UTF8"); // construct the original BigInteger BigInteger x1 = new BigInteger(ns); } catch (UnsupportedEncodingException ex) { // handle error }
Do not try to convert the String
object to a byte array to obtain the original BigInteger
. Character encoded data may yield a byte array that, when converted to a BigInteger
, results in a completely different value.
Exceptions
FIO11-EX0: Binary data that is expected to be a valid string may be read and converted to a string. How to perform this operation securely is explained in rule IDS13-J. Use compatible encodings on both sides of file or network IO. Also see rule IDS10-J. Do not split characters between two data structures.
Risk Assessment
Attempting to read a byte array containing binary data as if it were character data can produce erroneous results.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
FIO11-J |
low |
unlikely |
medium |
P2 |
L3 |
Bibliography
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="b7b22c13-38d3-409c-add5-83868a09c484"><ac:plain-text-body><![CDATA[ |
[[API 2006 |
AA. References#API 06]] |
[Class String |
http://java.sun.com/javase/6/docs/api/java/lang/String.html] |
]]></ac:plain-text-body></ac:structured-macro> |