T5WTPYAFGP - Encrypt Sensitive Information

At  South by Southwest  this year, during my talk  Defense Against The Dark Arts - ESAPI  I covered the "Top 5 Ways To Protect Your Application From Getting Pwnd" [T5WTPYAFGP]. After a couple offline conversations I decided that this would make an excellent series of follow-up blog posts so what follows is the adaptation of that presentation material from that talk. Unlike a lot of other Top-N lists, the goal of this one is not to iterate the flaws, but rather to iterate the solutions.

Additionally each post includes some samples on how you can use  ESAPI  to implement the solutions discussed and gives us the opportunity to dive into each area a little deeper than we were able to in a one-hour presentation.


You can use the navigation below to navigate between each of the posts.

[5] Encrypt Sensitive Information [current]
[4] Become Big Brother

5. Encrypt Sensitive Information
Number five on our list is to encrypt sensitive information. To understand this one we first need to define what actually constitutes sensitive information.

Most organizations that store credit card numbers are (hopefully) storing those credit card numbers in an encrypted format already, but what about the rest of the information that is stored. Think about your own organization or application - what information do you collect from your users?

According to published information, anything that is personally identifiable information, financial information, or medical information is to considered sensitive data and should be treated accordingly. Any organization that has to deal with standards verification will generally check the box for storage of sensitive information as long as that information is stored on an encrypted volume. This protects your customers from physical theft but what about run-time theft, which accounts for most of the largest breaches that occurred last year.

The key is to examine the risk for your application, determine what information would be damaging to release for your customers, and encrypt that data at rest. A lot of organizations simply don't want to incur the performance penalties of performing encryption and decryption of client data but some things are simply too important to ignore.

There are a number of ways to help mitigate the performance impact of using encryption in an application  and we will cover a few of them in this post.

The important thing is that once you have encryption configured (ie you have selected a provider and algorythm) actually performing the encryption and decryption of sensitive information is incredibly simple. 

  1. // Populate User Object from Request  
  2. // ...  
  3. // Encrypt Sensitive Information  
  4. CipherText encryptedSSN = ESAPI.encryptor().encrypt(new PlainText(userInfo.getSSN()));  
  5. userInfo.setSSN(new String(encryptedSSN.asPortableSerializedByteArray());  
  6. // Persist User Object  
  7. // ...  

To decrypt the data is just as simple. 
  1. // Retrieve persisted User Object  
  2. // ...  
  3. // Decrypt Sensitive Information  
  4. CipherText encryptedSSN = CipherText.fromPortableSerializedBytes(user.getSSN());  
  5. PlainText decryptedSSN = ESAPI.encryptor().decrypt(encryptedSSN);  
  6. userInfo.setSSN(decryptedSSN.toString());  
  7. // Prepare User Object for use in application  
  8. // ...  

Of course this can be abstracted into a service, added as an annotation processor in your persistence layer, and altered to be used in a more generic form that meets your specific platform needs. Additionally, depending on the type of information you are dealing with and the perceived risk of that information being leaked - it may make sense for the data to be encrypted  all the time  until it needs to be viewed or altered on the front end. This approach can also increase performance of the encryption and decryption because you are only ever performing this step when it is needed.

A comprehensive design is a little beyond the scope of this post, but when I do design I like to envision the end goal - that is what will the object I am protecting look like when I am done. To take the concept of the UserInfo object - here is what I envision as the end results:


  1. public class UserInfo implements Serializable {  
  2.    private final static long serialVersionID = 1L;  
  3.   
  4.    private Long id;  
  5.    private String username;  
  6.   
  7.    // This field will be stored in-memory and persisted as a hashed value using SHA-256   
  8.    @Sensative(type=SensitiveDataProtection.Type.HASH,  
  9.               algo=SensitiveDataProtection.Algo.SHA256  
  10.               mode=SensitiveDataProtection.Mode.RUNTIME)  
  11.    private String password;  
  12.   
  13.    // This field will be stored in-memory and persisted as an encrypted value using the SecretKey "UserData.SSN" for encryption and decryption  
  14.    @Sensitive(type=SensitiveDataProtection.Type.ENCRYPTED,  
  15.               key="UserData.SSN",  
  16.               mode="SensitiveDataProtection.Mode.RUNTIME)  
  17.    private String ssn;  
  18.   
  19.    // This field will be persisted as an encrypted value using the Master SecretKey but will be stored in-memory as a PlainText representation  
  20.    @Sensitive(type=SensitiveDataProtection.Type.ENCRYPTED,  
  21.               mode=SensitiveDataProtection.Mode.PERSIST)  
  22.    private String address;  
  23. }  


This looks pretty simple to implement for a developer and seems to address a lot of design needs, particularly the need to apply encryption only at the point where it is required. Annotations aren't for everyone however, so how can we accomplish a similar design goal without using Annotations? 

  1. public class UserInto implements Serializable {  
  2.    private final static long serialVersionID = 1L;  
  3.   
  4.    private Long id;  
  5.    private String username;  
  6.   
  7.    // This field will be stored in-memory and persisted as a hashed string  
  8.    private HashString password;  
  9.    // This field will be stored in-memory and persisted as an encrypted string  
  10.    private CipherText ssn;  
  11.    // This field will be persisted as an encrypted string  
  12.    private PlainText address;  
  13. }  


This example relies on the usage of data-types to specify the behavior of the data. While this breaks some rules in the world of design, it illustrates a possible solution to the problem.

Now do not be fooled into thinking that these solutions are simple to implement, they aren't - however the benefit of centralizing a standard control to perform this work is that you only have to write it once, you only have to maintain it in one place, and every developer of your application doesn't have to understand how the process works, just that it does.

In closing, here are each of the steps you should perform to address this problem and resolve it.

  1. Identify sensitive data in your application
  2. Design and implement a standard and centralized control
  3. Apply encryption to sensitive data in your application
Stay tuned for #4 on our top 5 list "Become Big Brother"!
Mybatis-Mate-Encrypt 是 Mybatis-Mate 的一个插件,用于在 Mybatis 中对敏感数据进行加密和解密处理。 使用步骤如下: 1. 引入 Mybatis-Mate-Encrypt 依赖: ```xml <dependency> <groupId>com.github.mybatis-mate</groupId> <artifactId>mybatis-mate-encrypt</artifactId> <version>1.0.3</version> </dependency> ``` 2. 在 Mybatis 配置文件中配置插件: ```xml <plugins> <plugin interceptor="com.github.mybatis.mate.encrypt.EncryptInterceptor"> <!-- AES加密key --> <property name="aesKey" value="1234567890123456"/> <!-- 加密字段配置 --> <property name="encryptColumns"> <!-- 配置表名、列名、加密类型 --> <encryptColumn tableName="user" columnName="password" encryptType="AES"/> </property> </plugin> </plugins> ``` 3. 在 Java 实体类中使用 @EncryptField 注解标注需要加密的字段: ```java public class User { private Integer id; private String username; @EncryptField(type = EncryptType.AES) private String password; // getter 和 setter 略 } ``` 4. 在 Mapper.xml 文件中使用 ${} 访问加密字段: ```xml <select id="getUserById" resultType="User"> select id, username, ${password} as password from user where id = #{id} </select> ``` 5. 在 Service 中调用 Mapper 方法即可: ```java public User getUserById(Integer id) { return userMapper.getUserById(id); } ``` 以上就是 Mybatis-Mate-Encrypt 的使用方法。需要注意的是,Mybatis-Mate-Encrypt 目前只支持 AES 加密和解密。如需使用其他加密算法,可以自行扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值