Perhaps someone need to use USB-KEY or other Hardware Token to generate Digital Signature , through Microsoft CryptoAPI. Perhaps MS CryptoAPI is the only way for us to access Cryptography Device such as USB-Key. It is sure not a comfortable way because Java developers have to call CAPI funtions throught JNI(Java Native Interface). So there are some java-library to CALL CryptoAPI, but they are not free.
I hope to provide an OpenSource Java Library to do this thing : SecureX[https://sourceforge.net/projects/securex]
Here is some demo of what SecureX Library could do:
1, SecureX Library Arichtecture Demo
http://dev2dev.bea.com.cn/bbs/servlet/D2DServlet/download/29304-31620-211417-3031/securex.swf
2, SecureX USB-Key Demo
http://dev2dev.bea.com.cn/bbs/servlet/D2DServlet/download/29304-31620-213693-3060/HNISI_SecureX_USBKey.swf
OK, Came back to our topic, how to use java call CryptoAPI to produce signature.
You should know at least :
1, CryptoAPI are just a set of interface define by MS, and USB-Key Vendor just implement these interface so that our application can call the usb key to do some cryptographic operations(eg Signature, Hash, Encryption). There are a lot of CSPs located in your windows system. CSP is implementation, but we need not care about it, All we care is what CryptoAPI could do. See MSDN for more information.
2, For Java developer, they should use JNI to access CryptoAPI but it is not an easy thing since there are some encoding difference between JDK and Windows. For example, they should know how to convert the binary Private key stream to Java PrivateKey Object.
3, Perhaps some USB-Key vendor provide PKCS#11 CSP other than CryptoAPI CSP. PKCS# CSP is a RSA Standard [http://www.rsasecurity.com/rsalabs/node.asp?id=2133], It will be a good optional implement instead of CryptoAPI CSP.
Back to CryptoAPI CSP:
Java developer should do such a thing to generate a signature:
byte
[] data
=
"
http://openssl.blogjava.net
"
.getBytes();
SignatureUtils sigutil
=
new
SignatureUtils(
"
MD5
"
);
sigutil.initSign(privateKey);
sigutil.update(data,
0
,data.length);
byte
[] signature
=
sigutil.sign();
sigutil.initVerify(publicKey);
sigutil.update(data,
0
,data.length);
if
(
!
sigutil.verify(signature))
System.out.println(
"
The signature verification failed.
"
);
else
System.out.println(
"
The signature was successfully verified.
"
);
before we sign, we should provide a privatekey, in the java world, private key is stored in JKS file(Java Keystore), we could get the keyEntry out through:
keyStoreStream
=
new
FileInputStream(keyStoreFilename);
keystore
=
KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(keyStoreStream, keyStorePassword.toCharArray());
Key key
=
keystore.getKey(alias, keypassword);
if
(key
instanceof
PrivateKey)
return
(PrivateKey)key;
But on windows, private key is not stored in JKS, they stored in Windows Local CertStore or in USB-Key,and in most cases, private key are not allowed to Export!
In CryptoAPI's world, you should do the following things.
call CryptAcquireContext get HCRYPTPROV handle, also known as a csp handle
call CryptCreateHash to hash your data
call CryptSignHash to sign
CryptAcquireContext need Key container name 、CSP Name、CSP type、dwFlags。
CryptCreateHash need hash agorithm
CryptSignHash need dwKeySpec,right! it's the private key spec.
So, Java developer feel boring when he need to provide the private key.
The proper way is:
1, Use Alias to get the privatekey:
(a) if the private key is exportable, we can get it and change it to a Java Object
(b) if the private key is not exportable, we get the private key handle.
2, Sign the Hash
(a) if the private key is exportable, sigutil.initSign(privateKey) would do this job.
(b) if the private key is not exportable, we pass the private key handle to CSP,
and let CSP get the privatekey internally.
The program below is running under securex, and it can get the privatekey from
usb-key, and sign the data:
/** *//**
* 签名,并将XML签名结果保存到signatureFile中
* 需要3个条件
* 1,KeyAlias,用于获取私钥
* 2,source_filename_to_be_signed,确定被签名的数据源
* 3,签名算法
* @param save_signatureFile
*/
public static void sign()
{
byte abyte0[][];
if((abyte0 = CorKeyStoreJNI.getKey(getKeyAlias())) == null)
{
System.err.println("这是一条不可导出的钥匙!");
return;
}
if(abyte0.length == 0)
{
JCAPIRSAPrivateKey jcapikey =new JCAPIRSAPrivateKey(getKeyAlias().getBytes());
System.out.println(jcapikey.getAlgorithm()+":"+jcapikey.getPrivateExponent());
/** *//**
* 签名数据
*/
File sourcefile=new File(source_filename_to_be_signed);
byte[] data =null;
try {
data= FileUtils.getBytesFromFile(sourcefile);
} catch (IOException e1) {
e1.printStackTrace();
}
byte[] signature=null;
/** *//**
* 产生签名
* TODO, 使用正确的签名算法,比如MD5withRSA->MD5
*/
SignatureUtils sigutil=new SignatureUtils(getSignAgorithm());
try {
sigutil.initSign(jcapikey);
sigutil.update(data,0,data.length);
signature = sigutil.sign();
System.out.println("signature>>>.."+new String(signature));
setRawSignature(signature);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (SignatureException e) {
e.printStackTrace();
}
/** *//**
* 保存签名到save_signatureFile
* 也就是sign的参数
*/
try {
FileUtils.writeFile(getSaveSignatureFile(),signature);
} catch (IOException e) {
e.printStackTrace();
}
}
} How's it done?
1) Well, Suppose I USE an USB E-Key(CSP Vendor
:吉大正元www.jit.com.cn)
I know my PrivateKey Alias is , Locate In "My"
I get the private key through CoreKeyStoreJNI Class which has native jni method(getKey), by which I could
tell the csp which private key i want to use!
2) I get the file to byteArray which must be Hash before sign, because for Microsoft CAPI, its signobject can accept hash object only.
SignatureUtils sigutil=new SignatureUtils(getSignAgorithm());
the getSignAgorithm return "MD5withRSA" "SHA1withRSA" for most cases. It meas MD5 data before RSA Sign :)
3) when the
sigutil.sign(); is Excute, a native PIN-CallBack Windows is open, it will ask you for private key protected password(you can see it in my swf demo above).
type the correct PIN , My JIT CSP will call the correct sign cryptographic operations through the USB EKey drivers.
All the cryptographic operations(Hash, Sign) are performed on the USB-Key INTERNALLY, NOT by the KEY Drivers.
OK,then CSP get the signature and Signature Verify use only the Public Key and need not access the private key, It can perform by CSP or verify using JCE, as you like.
4) Haha, I've not yet told you that you need a DLL to Load before you call these API. Wait till I put my whole project to sourceforege SecureX(
http://securex.sourceforge.net/). Any Advice, please contact me on this blog or just join the QQ Group: 14966586
分享到:
相关推荐
USBKEY windows中csp的编写
CSP开发基础大全 CSP开发基础大全 CSP开发基础大全
CryptoAPI(一个应用程序编程接口)目的就是提供开发者在Windows下使用PKI的编程接口。CryptoAPI提供了很多函数,包括编码、解码、加密、解密、哈希、数字证书、证书管理和证书存储等功能。对于加密和解密,Crypto...
微软加密服务体系CryptoAPI的结构如下图所示,微软加密服务体系包含三层结构和两个接口,分别为应用程序层、操作系统层(OS)、加密服务提供者层(Cryptographic Service Provider,CSP),CryptoAPI接口和加密服务提供...
在这个信息爆炸的时代,我们不得不对信息的安全提高警惕。加密作为保障数据信息安全的一种方式,越来越受到人们的关注。...我将把自己对Microsoft CryptoAPI的一些肤浅的理解与大家共享,有什么不妥之处望不吝赐教。
CryptoAPI培训教程,包含了所有CryptoAPI函数介绍、CryptoAPI编程实例等等。
微软加密服务体系CryptoAPI的结构如下图所示,微软加密服务体系包含三层结构和两个接口,分别为应用程序层、操作系统层(OS)、加密服务提供者层(Cryptographic Service Provider,CSP),CryptoAPI接口和加密服务提供...
Delphi使用CryptoAPI生成自签名证书,PHP端使用该证书进行签名,Delphi作为客户端使用公钥进行验签。
用 Microsoft CryptoAPI对数据进行加解密.pdf
CryptoAPI实例源码,学CryptoAPI看看吧,有帮助
*CryptoAPI数据加解密,它的流程为: *(加密模块)1.创建会话密钥 2.加密数据 3.安全保存或交换会话密钥 *(解密模块)1.获取会话密钥 2.解密数据 *它的加密是基于对称加密算法的(对称算法加密解密速度快),对...
CryptoAPI培训教程.pdf 在VC中用CryptoAPI保证安全数据通信.pdf
本文整理了如何使用CryptoAPI 操作ukey进行数字签名。附上流程和部分代码,讲解cryptoapi实际应用以及应用中关键问题的解决方法,在这里,仅介绍数字签名(加密流程类似,但是,操作略有不同,所需要的函数也不同),...
利用CryptoAPI对硬件CSP操作的分析分享.pdf
这是一次大三的信息安全的实验,利用CryptoAPI 实现对称密钥加密、公钥密钥加密和数字签名,还有良好的界面,使用VS2008开发的,里面包含全部的源代码。希望能和大家相互交流学习。
CryptoAPI加密解密代码,vc6.0工程源代码,可以正常加密解密
Microsoft CryptoAPI加密技术 源代码.zip
C语言编写的,利用下CryptoAPI加密系统,代码有详细注释。
用CryptoAPI生成密钥的方法.pdf