Java安全——消息摘要

简介:

标签(空格分隔): Java 安全


[toc]


概念

消息摘要(Message Digest)又称为数字摘要(Digital Digest)。它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生。如果消息在途中改变了,则接收者通过对收到消息的新产生的摘要与原摘要比较,就可知道消息是否被改变了。因此消息摘要保证了消息的完整性。 消息摘要采用单向Hash 函数将需加密的明文"摘要"成一串128bit的密文,这一串密文亦称为数字指纹(Finger Print),它有固定的长度,且不同的明文摘要成密文,其结果总是不同的,而同样的明文其摘要必定一致。这样这串摘要便可成为验证明文是否是"真身"的"指纹"了。 <<百度百科>>

消息摘要其实是我们日常开发中经常遇到的,比如MD5算法就是一种摘要。它是Java安全提供者体系中最简单的标准引擎。本文不会讨论算法本身,只关注Java语言体系中的实现和使用方法。具体算法原理,后续撰文学习并补充。

使用

消息摘要通过MessageDigest类实现。消息摘要通过getInstance()方法获取算法实例。通过update()方法为消息摘要增加内容字节。根据digest()方法利用累计的内容字节计算最后的摘要。

下面的test列出了一些细节:

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

import org.apache.commons.codec.binary.Hex;

public class MessageDigestTest {

    private static String TEST_DATA = "i am a test";

    public static void main(String[] args)
                    throws NoSuchAlgorithmException, UnsupportedEncodingException {
        MessageDigest md = MessageDigest.getInstance("SHA");
        print(md);
        md = MessageDigest.getInstance("MD5");
        print(md);
        md = MessageDigest.getInstance("MD2");
        print(md);
        md = MessageDigest.getInstance("SHA-256");
        print(md);
        md = MessageDigest.getInstance("SHA-384");
        print(md);
        md = MessageDigest.getInstance("SHA-224");
        print(md);
        md = MessageDigest.getInstance("SHA-512");
        print(md);
    }

    private static void print(MessageDigest md) throws UnsupportedEncodingException {
        System.out.println("Algorithm:\t" + md.getAlgorithm());
        System.out.println("\tProvider:\t" + md.getProvider());
        long start = System.nanoTime();
        md.update(TEST_DATA.getBytes("UTF-8"));
        byte[] digest = md.digest();
        long time = System.nanoTime() - start;
        System.out.println("\tTime cost:\t" + time + "ns");
        System.out.println("\tByte length:\t" + digest.length);
        String digestBase64Str = Base64.getEncoder().encodeToString(digest);
        System.out.println("\tBase64:\t" + digestBase64Str + "\tlen:\t" + digestBase64Str.length());
        String digestHexStr = Hex.encodeHexString(digest);
        System.out.println("\tHex:\t" + digestHexStr + "\tlen:\t" + digestHexStr.length());
    }
}

输出结果如下:

Algorithm:    SHA
    Provider:    SUN version 1.8
    Time cost:    432582ns
    Byte length:    20
    Base64:    Bj5BsD+J+PLpYZYVDR+14WwSKlg=    len:    28
    Hex:    063e41b03f89f8f2e96196150d1fb5e16c122a58    len:    40
Algorithm:    MD5
    Provider:    SUN version 1.8
    Time cost:    46030ns
    Byte length:    16
    Base64:    dCVplUXLIKBlw/aWvoOCyA==    len:    24
    Hex:    7425699545cb20a065c3f696be8382c8    len:    32
Algorithm:    MD2
    Provider:    SUN version 1.8
    Time cost:    80611ns
    Byte length:    16
    Base64:    v4z32/PgSXZCrWvnOcRiaQ==    len:    24
    Hex:    bf8cf7dbf3e0497642ad6be739c46269    len:    32
Algorithm:    SHA-256
    Provider:    SUN version 1.8
    Time cost:    205859ns
    Byte length:    32
    Base64:    lRctjSY3GOo6erswsyheP21CNtAAGxnsUHVF17u7RYg=    len:    44
    Hex:    95172d8d263718ea3a7abb30b3285e3f6d4236d0001b19ec507545d7bbbb4588    len:    64
Algorithm:    SHA-384
    Provider:    SUN version 1.8
    Time cost:    258382ns
    Byte length:    48
    Base64:    /B642f1Y+PPKgeIJHFpbEDLJwX2nqWaMaC8nVQuboRWN5MZeKpGaLiySWUEr4xB9    len:    64
    Hex:    fc1eb8d9fd58f8f3ca81e2091c5a5b1032c9c17da7a9668c682f27550b9ba1158de4c65e2a919a2e2c9259412be3107d    len:    96
Algorithm:    SHA-224
    Provider:    SUN version 1.8
    Time cost:    76539ns
    Byte length:    28
    Base64:    6m2pv1G0lnWlKO4ahn7iJAQF8XMo5cHR3LBO3w==    len:    40
    Hex:    ea6da9bf51b49675a528ee1a867ee2240405f17328e5c1d1dcb04edf    len:    56
Algorithm:    SHA-512
    Provider:    SUN version 1.8
    Time cost:    143649ns
    Byte length:    64
    Base64:    Vv6LL9QqfeCq1ClbN8JdMTcU1PzUbsRQKgmc7vVDbcHTB6i/SryXIjWcRcrfYa6n2QxstmSwUY9AME3pTmykNw==    len:    88
    Hex:    56fe8b2fd42a7de0aad4295b37c25d313714d4fcd46ec4502a099ceef5436dc1d307a8bf4abc9722359c45cadf61aea7d90c6cb664b0518f40304de94e6ca437    len:    128

消息摘要实现是通过Java自己Sun的实现来做的。我们常见的是MD5和SHA算法。

安全消息摘要

考虑到消息摘要的不安全性——拿到原文并知道算法,就可以得到正确的消息摘要。人们又加入了密钥元素,得到了安全消息摘要——MAC(Message Authentication Code)。MAC的特点是仅通过原文是无法计算出安全消息摘要的。还需要一个双方都知道的消息密钥。如果有人修改了消息本体,又修改了消息摘要,但是因为没有使用密钥,那么将被发现破坏了数据。计算MAC的方法有很多,但是核心Java API没有相关实现。Java的实现主要是通过JCE提供者来实现的。Mac类对应消息摘要的MessageDigest类。计算消息摘要时需要一个密钥。密钥的管理是另一个话题了。这里主要讲MAC的算法,JCE实现主要基于HmacSHA1和HmacMD5。具体provider提供了哪些MAC相关的算法,它们比较如何,见下面的代码:

package com.taobao.cd.security;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;

import org.apache.commons.codec.binary.Hex;

public class MacTest {

    public static String TEST_DATA = "I am test";

    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException {
        // TODO Auto-generated method stub
        Mac mac = Mac.getInstance("HmacSHA1");
        print(mac);
        mac = Mac.getInstance("HmacMD5");
        print(mac);
        mac = Mac.getInstance("SslMacMD5");
        print(mac);
        mac = Mac.getInstance("HmacSHA384");
        print(mac);
        mac = Mac.getInstance("HmacSHA256");
        print(mac);
        mac = Mac.getInstance("HmacSHA224");
        print(mac);
        mac = Mac.getInstance("SslMacSHA1");
        print(mac);
        mac = Mac.getInstance("HmacSHA512");
        print(mac);
    }

    private static void print(Mac mac) throws NoSuchAlgorithmException, InvalidKeyException {
        System.out.println("Algorithm:\t" + mac.getAlgorithm());
        System.out.println("\tProvider:\t" + mac.getProvider());
        KeyGenerator kg = KeyGenerator.getInstance("DES");
        SecretKey key = kg.generateKey();
        long start = System.nanoTime();
        mac.init(key);
        mac.update(TEST_DATA.getBytes());
        byte[] digest = mac.doFinal();
        long time = System.nanoTime() - start;
        System.out.println("\tTime cost:\t" + time + "ns");
        System.out.println("\tByte length:\t" + digest.length);
        String digestBase64Str = Base64.getEncoder().encodeToString(digest);
        System.out.println("\tBase64:\t" + digestBase64Str + "\tlen:\t" + digestBase64Str.length());
        String digestHexStr = Hex.encodeHexString(digest);
        System.out.println("\tHex:\t" + digestHexStr + "\tlen:\t" + digestHexStr.length());
    }
}

输出如下:

Algorithm:    HmacSHA1
    Provider:    SunJCE version 1.8
    Time cost:    259396ns
    Byte length:    20
    Base64:    SVaesT3JpL9Emz5O40aZhpUrX5s=    len:    28
    Hex:    49569eb13dc9a4bf449b3e4ee3469986952b5f9b    len:    40
Algorithm:    HmacMD5
    Provider:    SunJCE version 1.8
    Time cost:    136070ns
    Byte length:    16
    Base64:    hBDkDPJ1CpyYqvFN48chqQ==    len:    24
    Hex:    8410e40cf2750a9c98aaf14de3c721a9    len:    32
Algorithm:    SslMacMD5
    Provider:    SunJCE version 1.8
    Time cost:    174089ns
    Byte length:    16
    Base64:    YiEubyE7y+M4JesHQOAV7A==    len:    24
    Hex:    62212e6f213bcbe33825eb0740e015ec    len:    32
Algorithm:    HmacSHA384
    Provider:    SunJCE version 1.8
    Time cost:    648249ns
    Byte length:    48
    Base64:    GLic/lwKBA1DdQVbNF5y7L/H8o+0gcO1n02JcdUJMnE9MRwyfHWamEsAJL3ycfFy    len:    64
    Hex:    18b89cfe5c0a040d4375055b345e72ecbfc7f28fb481c3b59f4d8971d50932713d311c327c759a984b0024bdf271f172    len:    96
Algorithm:    HmacSHA256
    Provider:    SunJCE version 1.8
    Time cost:    26007ns
    Byte length:    32
    Base64:    7LGdb6W8WPYfOXx0WQQ8f35zSGCxs/6op6eOqStuGxA=    len:    44
    Hex:    ecb19d6fa5bc58f61f397c7459043c7f7e734860b1b3fea8a7a78ea92b6e1b10    len:    64
Algorithm:    HmacSHA224
    Provider:    SunJCE version 1.8
    Time cost:    125344ns
    Byte length:    28
    Base64:    adoBxnZuCle/ip4FyfCgiQUCmlaN1+RDch9Q9g==    len:    40
    Hex:    69da01c6766e0a57bf8a9e05c9f0a08905029a568dd7e443721f50f6    len:    56
Algorithm:    SslMacSHA1
    Provider:    SunJCE version 1.8
    Time cost:    50672ns
    Byte length:    20
    Base64:    RxCsQguxNXgtqcobgqWdvJeYTKo=    len:    28
    Hex:    4710ac420bb135782da9ca1b82a59dbc97984caa    len:    40
Algorithm:    HmacSHA512
    Provider:    SunJCE version 1.8
    Time cost:    365908ns
    Byte length:    64
    Base64:    /Vf5JsSle43/t4aUMkDfdDeUFg3CA0OQAt5izo0bgoUmaVrVOv3tjTLwmrrL/3kACVn38aIDSAIlz8725gl6lA==    len:    88
    Hex:    fd57f926c4a57b8dffb786943240df743794160dc203439002de62ce8d1b828526695ad53afded8d32f09abacbff79000959f7f1a203480225cfcef6e6097a94    len:    128

这里使用的key是通过KeyGenerator生成的。在实际应用中,应该有一方来生成并导出到可管理的KeyStore,使用方载入Keystore再进行摘要生成和校验。

目录
相关文章
|
1月前
|
SQL 安全 Java
安全问题已经成为软件开发中不可忽视的重要议题。对于使用Java语言开发的应用程序来说,安全性更是至关重要
在当今网络环境下,Java应用的安全性至关重要。本文深入探讨了Java安全编程的最佳实践,包括代码审查、输入验证、输出编码、访问控制和加密技术等,帮助开发者构建安全可靠的应用。通过掌握相关技术和工具,开发者可以有效防范安全威胁,确保应用的安全性。
48 4
|
14天前
|
SQL 安全 Java
Java 异常处理:筑牢程序稳定性的 “安全网”
本文深入探讨Java异常处理,涵盖异常的基础分类、处理机制及最佳实践。从`Error`与`Exception`的区分,到`try-catch-finally`和`throws`的运用,再到自定义异常的设计,全面解析如何有效管理程序中的异常情况,提升代码的健壮性和可维护性。通过实例代码,帮助开发者掌握异常处理技巧,确保程序稳定运行。
26 0
|
2月前
|
安全 Java 编译器
Java 泛型深入解析:类型安全与灵活性的平衡
Java 泛型通过参数化类型实现了代码重用和类型安全,提升了代码的可读性和灵活性。本文深入探讨了泛型的基本原理、常见用法及局限性,包括泛型类、方法和接口的使用,以及上界和下界通配符等高级特性。通过理解和运用这些技巧,开发者可以编写更健壮和通用的代码。
|
3月前
|
安全 Java API
java安全特性
java安全特性
29 8
|
3月前
|
安全 Java API
【性能与安全的双重飞跃】JDK 22外部函数与内存API:JNI的继任者,引领Java新潮流!
【9月更文挑战第7天】JDK 22外部函数与内存API的发布,标志着Java在性能与安全性方面实现了双重飞跃。作为JNI的继任者,这一新特性不仅简化了Java与本地代码的交互过程,还提升了程序的性能和安全性。我们有理由相信,在外部函数与内存API的引领下,Java将开启一个全新的编程时代,为开发者们带来更加高效、更加安全的编程体验。让我们共同期待Java在未来的辉煌成就!
72 11
|
3月前
|
安全 Java API
【本地与Java无缝对接】JDK 22外部函数和内存API:JNI终结者,性能与安全双提升!
【9月更文挑战第6天】JDK 22的外部函数和内存API无疑是Java编程语言发展史上的一个重要里程碑。它不仅解决了JNI的诸多局限和挑战,还为Java与本地代码的互操作提供了更加高效、安全和简洁的解决方案。随着FFM API的逐渐成熟和完善,我们有理由相信,Java将在更多领域展现出其强大的生命力和竞争力。让我们共同期待Java编程新纪元的到来!
110 11
|
4月前
|
前端开发 开发者 安全
JSF支付功能大揭秘:探索如何在Java世界中实现安全无缝的在线支付体验
【8月更文挑战第31天】在电子商务和在线交易日益普及的今天,实现在线支付功能已成为许多Web应用的必备需求。JavaServer Faces (JSF) 作为一种流行的Java Web框架,提供了丰富的组件和工具来构建用户界面,包括与支付网关集成以实现在线支付。支付网关是处理信用卡和借记卡支付的系统,在商家和银行之间起到桥梁作用。本文将探讨如何使用JSF与支付网关集成,以及实现在线支付功能时需要考虑的关键点
51 0
|
安全 Java
Java安全管理器
总的来说,Java安全应该包括两方面的内容,一是Java平台(即是Java运行环境)的安全性;二是Java语言开发的应用程序的安全性。
1356 0
|
安全 算法 Java
《Java安全编码标准》一1.9 安全管理器
本节书摘来自华章出版社《Java安全编码标准》一书中的第1章,第1.9节,作者 (美)Fred Long,Dhruv Mohindra,Robert C. Seacord,Dean F. Sutherland,David Svoboda,更多章节内容可以访问云栖社区“华章计算机”公众号查看
1743 0