Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: formatting fixes.

...

The subsequent code examples all involve the following code sample. This code sample posits a map that is serializable, as well as a function method to populate the map with interesting values, and a function method to check the map for those values.

Code Block
class SerializableMap<K,V> implements Serializable {
  final static long serialVersionUID = -2648720192864531932L;
  private Map<K,V> map;
  
  public SerializableMap() {
    map = new HashMap<K,V>();
  }

  public Object getData(K key)  {
    return map.get(key);
  }

  public void setData(K key, V data)  {
    map.put(key, data);
  }
}


public class MapSerializer {

  static public SerializableMap<static StringSerializableMap<String, Integer> buildMap() {
    SerializableMap< StringSerializableMap<String, Integer> map = new SerializableMap< StringSerializableMap<String, Integer>();
    map.setData("John Doe", new Integer( 123456789));
    map.setData("Richard Roe", new Integer( 246813579));
    return map;
  }

  public static public void InspectMap(SerializableMap< StringSerializableMap<String, Integer> map) {
    System.out.println("John Doe's number is " + map.getData("John Doe"));
    System.out.println("Richard Roe's number is " + map.getData("Richard Roe"));
  }

  public static void main(String[] args) {
    // ...
  }
}

...

Code Block
bgColor#FFcccc
public static void main(String[] args)
  throws IOException, ClassNotFoundException {
  // Build map
  SerializableMap< StringSerializableMap<String, Integer> map = buildMap();

  // Serialize map
  ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data"));
  out.writeObject( map);
  out.close();

  // Deserialize map
  ObjectInputStream in = new ObjectInputStream(new FileInputStream("data"));
  map = (SerializableMap< StringSerializableMap<String, Integer>) in.readObject();
  in.close();

  // Inspect map
  InspectMap( map);
}

If the data in the map is considered sensitive, this example will also violate SER03-J. Prevent serialization of unencrypted, sensitive data.

...

Code Block
bgColor#FFcccc
public static void main(String[] args)
  throws IOException, GeneralSecurityException, ClassNotFoundException {
  // Build map
  SerializableMap< StringSerializableMap<String, Integer> map = buildMap();

  // Generate sealing key & seal map
  KeyGenerator generator;
  generator = KeyGenerator.getInstance("AES");
  generator.init(new SecureRandom());
  Key key = generator.generateKey();
  Cipher cipher = Cipher.getInstance("AES");
  cipher.init( Cipher.ENCRYPT_MODE, key);
  SealedObject sealedMap = new SealedObject( map, cipher);

  // Serialize map
  ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data"));
  out.writeObject( sealedMap);
  out.close();

  // Deserialize map
  ObjectInputStream in = new ObjectInputStream(new FileInputStream("data"));
  sealedMap = (SealedObject) in.readObject();
  in.close();

  // Unseal map
  cipher = Cipher.getInstance("AES");
  cipher.init( Cipher.DECRYPT_MODE, key);
  map = (SerializableMap< StringSerializableMap<String, Integer>) sealedMap.getObject(cipher);

  // Inspect map
  InspectMap( map);
}

Noncompliant Code Example (Seal, Sign)

...

This noncompliant code example signs the object as well as sealing seals it. Unfortunately, the signing occurs after the sealing. As discussed aboveearlier, anyone can sign a sealed object, and so it cannot be assumed that the signer is the true originator of the object.

Code Block
bgColor#FFcccc
public static void main(String[] args)
  throws IOException, GeneralSecurityException, ClassNotFoundException {
  // Build map
  SerializableMap< StringSerializableMap<String, Integer> map = buildMap();

  // Generate sealing key & seal map
  KeyGenerator generator;
  generator = KeyGenerator.getInstance("AES");
  generator.init(new SecureRandom());
  Key key = generator.generateKey();
  Cipher cipher = Cipher.getInstance("AES");
  cipher.init( Cipher.ENCRYPT_MODE, key);
  SealedObject sealedMap = new SealedObject( map, cipher);

  // Generate signing public/private key pair & sign map
  KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
  KeyPair kp = kpg.generateKeyPair();
  Signature sig = Signature.getInstance("SHA1withDSA");
  SignedObject signedMap = new SignedObject( sealedMap, kp.getPrivate(), sig);

  // Serialize map
  ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data"));
  out.writeObject( signedMap);
  out.close();

  // Deserialize map
  ObjectInputStream in = new ObjectInputStream(new FileInputStream("data"));
  signedMap = (SignedObject) in.readObject();
  in.close();

  // Unsign map
  if (!signedMap.verify(kp.getPublic(), sig)) {
    throw new GeneralSecurityException("Map failed verification");
  }
  sealedMap = (SealedObject) signedMap.getObject();

  // Unseal map
  cipher = Cipher.getInstance("AES");
  cipher.init( Cipher.DECRYPT_MODE, key);
  map = (SerializableMap< StringSerializableMap<String, Integer>) sealedMap.getObject(cipher);

  // Inspect map
  InspectMap( map);
}

Compliant Solution (Sign, Seal)

...

Code Block
bgColor#ccccff
public static void main(String[] args)
  throws IOException, GeneralSecurityException, ClassNotFoundException {
  // Build map
  SerializableMap< StringSerializableMap<String, Integer> map = buildMap();

  // Generate signing public/private key pair & sign map
  KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
  KeyPair kp = kpg.generateKeyPair();
  Signature sig = Signature.getInstance("SHA1withDSA");
  SignedObject signedMap = new SignedObject( map, kp.getPrivate(), sig);

  // Generate sealing key & seal map
  KeyGenerator generator;
  generator = KeyGenerator.getInstance("AES");
  generator.init(new SecureRandom());
  Key key = generator.generateKey();
  Cipher cipher = Cipher.getInstance("AES");
  cipher.init( Cipher.ENCRYPT_MODE, key);
  SealedObject sealedMap = new SealedObject( signedMap, cipher);

  // Serialize map
  ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data"));
  out.writeObject( sealedMap);
  out.close();

  // Deserialize map
  ObjectInputStream in = new ObjectInputStream(new FileInputStream("data"));
  sealedMap = (SealedObject) in.readObject();
  in.close();

  // Unseal map
  cipher = Cipher.getInstance("AES");
  cipher.init( Cipher.DECRYPT_MODE, key);
  signedMap = (SignedObject) sealedMap.getObject(cipher);

  // Unsign map
  if (!signedMap.verify(kp.getPublic(), sig)) {
    throw new GeneralSecurityException("Map failed verification");
  }
  map = (SerializableMap<String, Integer>) signedMap.getObject();

  // Inspect map
  InspectMap( map);
}

Exceptions

Wiki Markup
*SER02-EX0:* A reasonable use for signing a sealed object is to certify the authenticity of a sealed object passed from elsewhere. In the spirit of the \[[Abadi 1996|AA. Bibliography#Abadi 96]\] quotation above, this represents a commitment _about the sealed object itself_ rather than about its content.

...

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="c45d6496ca37d23e-a9b6aaf3-44c64769-908b9881-f2cc78a26bb719dea9f1f779"><ac:plain-text-body><![CDATA[

[[MITRE 2009

AA. Bibliography#MITRE 09]]

[CWE ID 319

http://cwe.mitre.org/data/definitions/319.html] "Cleartext Transmission of Sensitive Information"

]]></ac:plain-text-body></ac:structured-macro>

...

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="cc532ce178ae8748-44e8d610-435a432b-9f0b8820-8f3fbbca1d4b9baca18b0f2d"><ac:plain-text-body><![CDATA[

[[API 2006

AA. Bibliography#API 06]]

 

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="fdc4762a4c6e1d7f-8b9e75ff-41854245-b2558660-ae40256a28f544edbf334e5b"><ac:plain-text-body><![CDATA[

[[Gong 2003

AA. Bibliography#Gong 03]]

9.10 Sealing Objects

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="d66b8c26a61e4079-9e3b2a76-4026419d-ba9b829d-64708b6c08457d301a52fc76"><ac:plain-text-body><![CDATA[

[[Harold 1999

AA. Bibliography#Harold 99]]

Chapter 11: Object Serialization, Sealed Objects

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="f44318180938324a-1f5054a9-4e494bbe-8477b52e-dd87752fb1ea4646d1812576"><ac:plain-text-body><![CDATA[

[[Neward 2004

AA. Bibliography#Neward 04]]

Item 64: Use SignedObject to provide integrity of Serialized objects

]]></ac:plain-text-body></ac:structured-macro>

 

Item 65: Use SealedObject to provide confidentiality of Serializable objects

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="22ae0f912a129eb5-8fe7257b-4ca44f4d-a9898cd0-cc6bff0ba994839518e1cd5b"><ac:plain-text-body><![CDATA[

[[Steel 2005

AA. Bibliography#Steel 05]]

Chapter 10: Securing the Business Tier, Obfuscated Transfer Object

]]></ac:plain-text-body></ac:structured-macro>

...