在Java应用程序中使用密码学

这篇文章描述了如何使用Java密码体系结构 (JCA),该体系结构使您可以在应用程序中使用密码服务。

Java密码体系结构服务

JCA提供了许多加密服务,例如消息摘要签名

这些服务可以通过特定于服务的API来访问,例如MessageDigestSignature

密码服务抽象了不同的算法。 例如,对于摘要,可以使用MD5SHA1 。 您可以将算法指定为加密服务类的getInstance()方法的参数:

MessageDigest digest = MessageDigest.getInstance("MD5");

您可以在“ JCA 标准算法名称文档”中找到算法参数的值。

一些算法具有参数。 例如,生成私钥/公钥对的算法将把密钥大小作为参数。 您可以使用initialize()方法指定参数:

KeyPairGenerator generator = KeyPairGenerator.getInstance("DSA");
generator.initialize(1024);

如果不调用initialize()方法,则将使用某些默认值,该默认值可能是您想要的,也可能不是。

不幸的是,用于初始化的API在服务之间并非100%一致。

例如, Cipher类将init()与指示加密或解密的参数一起使用,而Signature类将initSign()用于签名, initVerify()用于验证。

Java密码体系结构提供程序

JCA通过提供程序系统使您的代码独立于特定密码算法的实现。

提供商根据可配置的首选项顺序进行排名(请参见下文)。 最佳优先级是1,次佳是2,依此类推。优先级顺序允许JCA选择实现给定算法的最佳可用提供程序。

另外,您可以在getInstance()的第二个参数中指定特定的提供程序:

Signature signature = Signature.getInstance("SHA1withDSA", "SUN");

默认情况下,JRE附带了来自Oracle的一堆提供程序 。 但是,由于历史上的出口限制,这些并不是最安全的实现。 要获得更好的算法和更大的密钥大小,请安装Java密码学扩展无限强度管辖权策略文件

更新 :请注意,以上声明对Oracle JRE是正确的。 OpenJDK没有相同的限制

使您可以对密码学进行配置

您应始终确保应用程序使用的加密服务是可配置的。

如果这样做,则可以在不发布补丁的情况下更改密码算法和/或实现。

当对(一种实现)算法有新的攻击时,这特别有价值。

JCA使配置加密的使用变得容易。

getInstance()方法同时接受算法的名称和实现该算法的提供程序的名称。 您应该从某种配置文件中读取算法参数的值和所有值。

还要确保将代码DRY保留在一个地方并实例化加密服务。

检查所请求的算法和/或提供程序是否实际可用。

当给定的算法或提供程序不可用时, getInstance()方法将引发NoSuchAlgorithmException ,因此您应该捕获该异常。 然后最安全的选择是失败,并请他人确保系统配置正确。 如果在配置错误的情况下仍然继续,则可能会导致系统安全性低于要求。

请注意, Oracle建议不要指定提供程序 。 它们提供的原因是,并非所有提供程序都可以在所有平台上使用,并且指定提供程序可能意味着您错过了优化。

您应该权衡这些不利因素和易受攻击的风险。

在您的应用程序中部署具有已知特征的特定提供程序可能会消除Oracle提到的缺点。

添加加密服务提供商

提供程序系统是可扩展的,因此您可以添加提供程序。

例如,您可以使用开源Bouncy Castle或商业RSA BSAFE提供程序。

为了添加提供程序,必须确保其jar对应用程序可用。 为此,您可以将其放在类路径中。

另外,您可以通过将其放置在$JAVA_HOME/lib/ext目录中来使其成为已安装的扩展 ,其中$JAVA_HOME是JDK / JRE发行版的位置。

两种方法之间的主要区别在于,默认情况下, 已授予安装的扩展所有权限 ,而classpath上的代码则未被授予 。 当您的代码(的一部分)在沙盒中运行时,这非常重要。

某些服务(例如Cipher )要求对提供者jar进行签名

下一步是在JCA提供者系统中注册提供者。 最简单的方法是使用Security.addProvider()

Security.addProvider(new BouncyCastleProvider());

您还可以使用Security.insertProviderAt()方法设置提供者的优先顺序:

Security.insertProviderAt (new JsafeJCE(), 1);

这种方法的一个缺点是,它将代码耦合到提供程序,因为您必须导入提供程序类。 在像OSGi这样的模块化系统中,这可能不是重要的问题。

需要注意的另一件事是代码需要SecurityPermission以编程方式添加提供程序。

通过将注册项添加到java.security属性文件(可在$JAVA_HOME/jre/lib/security/java.security找到),还可以通过静态注册将提供程序配置为您环境的一部分:

security.provider.1=com.rsa.jsafe.provider.JsafeJCE
security.provider.2=sun.security.provider.Sun

该文件中的属性名称以security.provider.开头security.provider. 并以提供者的偏好结束。 该属性值是实现Provider的类的完全限定名称。

实施您自己的加密服务提供商

不要这样做 。 您弄错它,并且容易受到攻击。

使用加密服务提供者

提供程序的文档应告诉您将哪个提供程序名称用作getInstance()的第二个参数。 例如,Bouncy Castle使用BC ,而RSA BSAFE使用JsafeJCE

大多数提供程序都有自定义API以及符合JCA的API。 请勿使用自定义API,因为那样将无法配置所使用的算法和提供程序。

并非所有算法和实现都是相同的

重要的是要注意,不同的算法和实现具有不同的特性,这些特性或多或少会使它们适合您的情况。

例如,某些组织仅允许使用经过FIPS 140-2认证或在NSA Suite B加密算法列表中的算法和实现。

始终确保您了解客户的加密需求和要求。

在OSGi环境中使用JCA

getInstance()方法是使用服务提供商接口 (SPI)的工厂方法 。 这在OSGi世界中是有问题的,因为OSGi违反了SPI框架关于存在单个类路径的假设。

另一个潜在的问题是,JCA需要对一些jar进行签名。 如果这些罐子不是有效的OSGi捆绑包,则不能通过bnd来运行它们,因为这样会使签名无效。

幸运的是,您可以用一块石头杀死两只鸟。 将提供程序jar放在主程序(即启动OSGi框架的程序)的类路径中。

然后使用org.osgi.framework.system.packages.extra系统属性从OSGi系统捆绑包导出提供程序包。 这将使系统捆绑包导出该软件包。

现在,您可以简单地在包中的提供程序Import-Package上使用Import-Package

还有其他的选择 ,因为如果你不能使用上述方案解决这些问题。


参考: Secure Software Development博客上的JCG合作伙伴 Remon Sinnema提供了在Java应用程序中使用加密的信息

翻译自: https://www.javacodegeeks.com/2012/12/test-using-cryptography-in-java-applications.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值