zoukankan      html  css  js  c++  java
  • cookie防篡改

    概述:
    除了 session 外,一般不会在客户端的 cookies 里保存过于重要的凭据,但电商应用有时候不可避免地存储了一些敏感数据到客户端,当然不希望被篡改。

    目的:
    让服务器端能识别cookie值被篡改了。
     
    手法:
    set-cookie时加上防篡改验证码。
    如:
    user_name=alex|bj95ef23cc6daecc475de
     
    防篡改验证码的生成规则可以很简单:md5(cookieValue+key)或sha1(cookieValue+key),key可以是服务器端掌握的一个固定字符串,也可以很复杂(如后面的LTPA示例)。
     
    服务器端得到客户端送上来的cookie后,重新计算一下验证码,如一致,则未篡改。
     
    示例2:IBM LTPA 的 cookie 签名
    Lightweight Third-Party Authentication (LTPA)是IBM Websphere和Domino产品中使用的单点登录技术。
    当服务器配置好LTPA认证方式,用户通过浏览器成功登录后,服务器会自动发送一个 session cookie 给浏览器;此 Cookie 中包含一个 LTPA Token。
    一个有效的 LTPA Cookie 能够在同一个认证域中被所有服务器自动认证。此 Cookie 中包含认证信息和时间戳。这些信息通过共享的 3DES Key 进行了 bis  加密。使用公共密钥/私有密钥进行签名。
     
    1)大致介绍:
    LTPA Cookie 原始值 通过 3DES密钥 使用 DESede/ECB/PKCS5P 进行加密。
    此 3DES密钥  也是采用 DESede/ECB/PKCS5P 进行加密,加密后再使用事先提供的 密钥密码 进行SHA-1 Hash,生成24个字节的密钥,再进行Base64编码。
     
    如 Dmonio 里, LTPA Cookie 值为以下公式组成:
    SHA-1=LTPA版本号+创建时间+过期时间+用户名+Domino LTPA 密钥
    LTPA Cookie= Base64(LTPA版本号+创建时间+过期时间+用户名+SHA-1)
     
    如要解析 LTPA Token,先得使用 密钥密码,生成 3DES密钥;再使用 3DES密钥 解密 Token Cookie。也可以使用公共/私有密钥来签名或验证LTPA Cookie。

    2)WebSphere LTPA 生成原理

    首先,这个 cookie 由以下部分组成,以%进行分隔:
    • 用户信息,格式为u:user:<RealmName>/<UserDN>,如:u:user:VGOLiveRealm/CN=squallzhong,O=VGOLive Technology
    • 过期时间
    • 签名信息,如:
      u:user:VGOLiveRealm/CN=squallzhong,O=VGOLive Technology%1301558320666%Cy2CAeru5kEElGj0hrvYsKW2ZVsvvcu6Un573aeX55OO4G3EMYWc0e/ZbqDp1z7MS+dLzniuUH4sYWCMpnKdm7ZGabwmV+WcraBl+y+yzwcl722gHVMOnDZAW7U3jEay9Tk2yG4yXkMWU+617xndpVxke2jtS5wIyVVM3q7UDPw=

    3)WebSphere LTPA Cookie 的解析

    以下代码为解析从 WebSphere 或 Domino 发送过来的 LTPAToken Cookie。以Java为例:

    01
    02        // LTPA 3DES 密钥
    03        String ltpa3DESKey = "7dH4i81YepbVe+gF9XVUzE4C1Ca5g6A4Q69OFobJV9g=";
    04        // LTPA 密钥密码
    05        String ltpaPassword = "Passw0rd";
    06        try {
    07            // 第一步,获得加密key
    08            byte[] secretKey = getSecretKey(ltpa3DESKey, ltpaPassword);
    09            // 第二步,使用加密key解密ltpa Cookie
    10            String ltpaPlaintext = new String(decryptLtpaToken(tokenCipher,
    11                    secretKey));
    12            displayTokenData(ltpaPlaintext);
    13        } catch (Exception e) {
    14            System.out.println("Caught inner: " + e);
    15        }
    16
    17    //获得安全Key
    18    private static byte[] getSecretKey(String ltpa3DESKey, String password)
    19            throws Exception {
    20        // 使用SHA获得key密码的hash值
    21        MessageDigest md = MessageDigest.getInstance("SHA");
    22        md.update(password.getBytes());
    23        byte[] hash3DES = new byte[24];
    24        System.arraycopy(md.digest(), 0, hash3DES, 0, 20);
    25        // 使用0替换后4个字节
    26        Arrays.fill(hash3DES, 20, 24, (byte) 0);
    27        // BASE64解码 ltpa3DESKey
    28        byte[] decode3DES = Base64.decodeBase64(ltpa3DESKey.getBytes());
    29        // 使用key密码hash值解密已Base64解码的ltpa3DESKey
    30        return decrypt(decode3DES, hash3DES);
    31    }
    32    //解密LtpaToken
    33    public static byte[] decryptLtpaToken(String encryptedLtpaToken, byte[] key)
    34            throws Exception {
    35        // Base64解码LTPAToken
    36        final byte[] ltpaByteArray = Base64.decodeBase64(encryptedLtpaToken
    37                .getBytes());
    38        // 使用key解密已Base64解码的LTPAToken
    39        return decrypt(ltpaByteArray, key);
    40    }
    41    // DESede/ECB/PKC5Padding解方法
    42    public static byte[] decrypt(byte[] ciphertext, byte[] key)
    43            throws Exception {
    44        final Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
    45        final KeySpec keySpec = new DESedeKeySpec(key);
    46        final Key secretKey = SecretKeyFactory.getInstance("TripleDES")
    47                .generateSecret(keySpec);
    48        cipher.init(Cipher.DECRYPT_MODE, secretKey);
    49        return cipher.doFinal(ciphertext);
    50    }
    51

    解析出来的LTPAToken信息以%分隔。

    来源:http://www.cnblogs.com/zhengyun_ustc/archive/2012/11/17/topic3.html

  • 相关阅读:
    删除查询出以外的数据
    查询头3条
    查询共多少条记录
    Linq查询非泛型集合要指定Student类型(比如List)
    Linq to 泛型集合查询集合包括大写M和年龄小于等于18
    LINQ查询字符串判断是否大写
    LINQ查询数组里面是否包含某值
    Lambda表达式
    构建之法(四)
    构建之法(三)
  • 原文地址:https://www.cnblogs.com/gjhjoy/p/3495317.html
Copyright © 2011-2022 走看看