根据JEP 131,Java 8应该为64位Windows提供PKCS#11加密提供程序:https://blogs.oracle.com/mullan/entry/jep_131_pkcs_11_crypto。
考虑到这一点,我使用以下指令下载并构建了带有NSPR的32位和64位版本的NSS:https://developer.mozilla.org/en-US/docs/NSS_Sources_Building_Testing
我下载了Java 8 for Windows 64 build b118,配置了java.security文件并创建了一个nss.cfg文件:
摘自java.security文件:
security.provider.1=sun.security.provider.Sun
security.provider.2=sun.security.rsa.SunRsaSign
security.provider.3=sun.security.ec.SunEC
security.provider.4=com.sun.net.ssl.internal.ssl.Provider SunPKCS11-NSS
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC
security.provider.10=sun.security.pkcs11.SunPKCS11 /devel/nss.cfg
nss.cfg:
# Use NSS as a FIPS-140 compliant cryptographic token
# SunPKCS11-NSS
name = NSS
#32 bit
nssLibraryDirectory = C:\devel\nss\nss-3.15.3.1\dist\WINNT6.1_DBG.OBJ\lib
#64 bit
#nssLibraryDirectory = C:\devel\nss\nss-3.15.3.1\dist\WINNT6.1_64_DBG.OBJ\lib
#non FIPS
#nssDbMode = noDb
#attributes = compatibility
#FIPS
nssSecmodDirectory = c:\devel\fipsdb
nssModule = fips
我运行了NSS附带的测试套件,它看起来像通过了所有加密/解密测试一样(确实存在一些需要主机名/域名但与Windows环境有关的测试问题)。
所以这就是问题所在。我使用32位版本的NSS在Java 7 32位上运行测试加密应用程序,并且一切正常。当我尝试使用64位NSS运行Java 8 64位时,出现以下错误:
java.security.ProviderException: Could not initialize NSS
at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:212)
at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:103)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at sun.security.jca.ProviderConfig$2.run(Unknown Source)
at sun.security.jca.ProviderConfig$2.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.security.jca.ProviderConfig.doLoadProvider(Unknown Source)
at sun.security.jca.ProviderConfig.getProvider(Unknown Source)
at sun.security.jca.ProviderList.getProvider(Unknown Source)
at sun.security.jca.ProviderList.getIndex(Unknown Source)
at sun.security.jca.ProviderList.getProviderConfig(Unknown Source)
at sun.security.jca.ProviderList.getProvider(Unknown Source)
at java.security.Security.getProvider(Unknown Source)
at sun.security.ssl.SunJSSE.<init>(Unknown Source)
at sun.security.ssl.SunJSSE.<init>(Unknown Source)
at com.sun.net.ssl.internal.ssl.Provider.<init>(Unknown Source)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at sun.security.jca.ProviderConfig$2.run(Unknown Source)
at sun.security.jca.ProviderConfig$2.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.security.jca.ProviderConfig.doLoadProvider(Unknown Source)
at sun.security.jca.ProviderConfig.getProvider(Unknown Source)
at sun.security.jca.ProviderList.getProvider(Unknown Source)
at sun.security.jca.ProviderList$ServiceList.tryGet(Unknown Source)
at sun.security.jca.ProviderList$ServiceList.access$200(Unknown Source)
at sun.security.jca.ProviderList$ServiceList$1.hasNext(Unknown Source)
at javax.crypto.KeyGenerator.nextSpi(KeyGenerator.java:323)
at javax.crypto.KeyGenerator.<init>(KeyGenerator.java:158)
at javax.crypto.KeyGenerator.getInstance(KeyGenerator.java:208)
at STSAESEncryption.generateKeyWithGenerator(STSAESEncryption.java:74)
at Main.main(Main.java:24)
Caused by: java.io.IOException: %1 is not a valid Win32 application.
at sun.security.pkcs11.Secmod.nssLoadLibrary(Native Method)
at sun.security.pkcs11.Secmod.initialize(Secmod.java:210)
at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:207)
... 36 more
我确实向Sean Mullan的博客发布了一条消息(并在上面链接),并回答了该问题:一切都在运行64位,并且我无法使其在非FIPS模式下工作(相同的错误),但是我的答复没有显示在博客上(需要批准)。
是否有其他人试图让NSS在Windows 64位上使用Java 8 64位工作?
基于Alex Pakka评论的更新1:
感谢您的答复。使用Java 8 64位时,我正在使用64位NSS库。当我同时测试32位和64位时,一直在来回切换。
我附加了代码并逐步执行,但是当我尝试查看platformPath变量时,出现“platformPath无法解析为变量”的信息。我对Eclipse并不是很熟悉,所以我想知道我做错了什么。
我尝试编辑要放入的路径,以查看出现什么错误,并且将nssLibraryPath更改为另一个目录(不包含nss库)时,遇到了另一个错误,然后是win32。
我确实知道nss在Linux(以及可能的其他平台)上可与Java 8 64位一起使用,但是它是否已针对Windows 64位进行了验证。我知道这是Java 8和Windows 64位的新功能,而Java 7仅支持Windows 43位。
再次感谢您的答复,它有所帮助,我仍在设法弄清楚。
最佳答案
我可能不在这里了。
我不认为NSS已通过源代码格式(如OpenSSL)验证为FIPS 140-2。 NSS是一种更传统的验证,例如Crypto++,Certicom和其他验证。对于NSS,您必须从Mozilla获取预构建的二进制文件。
如果Mozilla不为您提供Windows的FIPS 140-2验证的二进制文件,或者不为您需要的Windows平台提供FIPS 140-2的验证二进制文件,那么我认为您很不走运。
最简单的判断方法可能是使用NIST对文件中的Network Security Services (NSS) Cryptographic Module Version 3.12.4 FIPS 140-2 Security Policy进行检查。 (我可能使用的版本不正确,因为我不使用NSS;请确保检查其最新的安全策略)。
根据1提到的“安全策略”,似乎只有两个已布局的平台,而Windows都不是。请参阅第2.2节,平台列表(第8页):
Model |Operating System and Version
------------------------------+----------------------------
x86_64 Nehalem Xeon 5500 |Wind River Linux Secure 1.0
------------------------------+----------------------------
x86_64 Pentium core2 duo |Wind River Linux Secure 1.0
从上表中,您需要使用Wind River Linux Secure 1.0。如果使用的是Wind River,则还必须具有Xeon 5500或Core2 Duo。否则,使用“验证密码学”将您变成而不是。
同样,Crypto++在Windows上具有三个FIPS 140-2验证(证书343、562和819)。但是,您需要从Crypto++网站下载预构建的二进制文件,并且需要根据NIST提交的Crypto++安全策略来使用它们。限制包括OS版本,甚至C运行时Service Pack级别。