...
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 | ||
---|---|---|
| ||
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 | ||
---|---|---|
| ||
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 | ||
---|---|---|
| ||
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 | ||
---|---|---|
| ||
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> |
...