使用 Java 的通用访问卡 (CAC) 身份验证

发布于 07-14 08:05 字数 851 浏览 10 评论 0原文

我基本上是在寻找一个地方来开始学习如何使用 java 与政府 CAC 卡交互。

最终,我的目标是了解如何使用 CAC 卡身份验证(通过 PIN 码)来授权访问使用 Tomcat/J2EE 服务器托管的网站。

但我需要从某个地方开始。 所以我想我首先要编写一个小的java程序来简单地从插入我键盘上的读卡器的CAC卡中读取CAC卡信息(DELL键盘,数字键盘上方有CAC读卡器)。

通过搜索google,我找到了cacard java项目(https://cacard.dev。 java.net/),已被 OpenSSO 项目取代。 但我似乎找不到如何使用它连接到卡、从卡读取数据等的示例代码。

有谁知道我在哪里可以找到一些示例代码,以便我可以开始学习如何与 CAC 交互使用java的卡?

谢谢

编辑:

经过更多研究后,我在想,我是否可以在 server.xml 文件的连接器元素中设置 clientAuth="true"

http://tomcat.apache.org/tomcat-6.0-doc/ssl -howto.html

clientAuth:如果您希望 Tomcat 要求所有 SSL 客户端提供客户端证书才能使用此套接字,请将此值设置为 true。

I'm bascially looking for someplace to start learning how to interface with a government CAC card using java.

Ultimately, my goal is to find out how to use CAC card authentication (by PIN number) to authorize access to a website hosted using a Tomcat/J2EE server.

But I'll need somewhere to start. So I figure I'd start by writing a small java program to simply read the CAC card information from the CAC card which is inserted into a card reader on my keyboard (DELL keyboard with CAC reader above the numeric keypad).

By searching google, I found the cacard java project (https://cacard.dev.java.net/) which was replaced by the OpenSSO project. But I can't seem to find sample code of how to use it to connect to a card, read from a card, etc.

Does anyone know where I can find some sample code so that I can start learning how to interact with a CAC card using java?

Thanks

EDIT:

After researching more, I was thinking, would I be able to just set clientAuth="true" in the connector element in the server.xml file?

http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html

clientAuth: Set this value to true if you want Tomcat to require all SSL clients to present a client Certificate in order to use this socket.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

妄司2024-07-21 08:05:34

您是在创建 Web 应用程序,还是尝试编写在客户端运行的软件(有点像您自己的 Web 浏览器)?

如果您正在创建一个 Web 应用程序,那么它几乎只是标准的客户端认证身份验证。 证书来自硬件令牌这一事实对于服务器来说并没有太大改变; 如果您只想接受 CAC 证书,您可以在服务器验证客户端证书时指定一组可接受的证书策略。 (策略验证是 PKIX 验证的标准部分。)如果此应用程序面向政府客户,您需要与他们的安全团队密切合作,以确保您的解决方案满足他们的要求,这些要求可能很严格。 如果这是您的情况,请告诉我,我将用我们遇到的一些问题更新我的答案。

如果您正在编写客户端,并且需要访问物理阅读器,则可以使用 Sun PKCS #11 提供程序,自 Java 1.5 起。 我已经尝试过这个提供程序,您可以在 另一个答案。


在服务器上,您应该检查证书是否未被吊销。 然而,其中一些 CRL 非常庞大,我们有超过 100 Mb 的 CRL 文件,而内置的 Sun 吊销检查程序无法很好地扩展到这种大小。

您还需要确保 Tomcat 的“信任”密钥存储中拥有正确的根 CA 证书(政府根 CA 证书不太难找到,因为他们希望确保用户正确验证它们)。 我们还发现,除非用户手动将中间证书导入浏览器,否则 Firefox 不会发送整个证书链。

Are you creating the web application, or trying to write software that runs at the client (sort of like your own web browser)?

If you are creating a web application, it's pretty much just standard client certification authentication. The fact that the certificate came from a hardware token doesn't change much for the server; if you want to accept only CAC certificates, you can specify set of acceptable certificate policies when the server validates the client certificate. (Policy validation is a standard part of PKIX validation.) If this application is for a government customer, you'll need to work closely with their security team to ensure that your solution meets their requirements, which can be stringent. If this is your scenario, let me know and I'll update my answer with some of the issues that we encountered.

If you are writing a client, and need to access the physical reader, you may be able to use the Sun PKCS #11 provider, since Java 1.5. I've experimented with this provider, and you can read more about it in another answer.


On the server, you should check that the certificate is not revoked. However, some of these CRLs are enormous—we had over 100 Mb worth of CRL files, and the built-in Sun revocation checker does not scale well to this size.

You will also need to make sure that you have the right root CA certificates in Tomcat's "trust" key store (the government root CA certs are little harder to find because they want to make sure users are verifying them properly). We also found that Firefox does not send the entire certificate chain unless users import the intermediate certificates into their browser manually.

佞臣2024-07-21 08:05:34

您需要创建一个名为 card.config 的文件,并在其中包含以下几行:

name = myConfig
library = /path/to/library/that/implements/cac/card/reader 

然后尝试执行此操作:

import java.io.*;
import java.util.*;

import java.security.cert.CertificateException;
import java.security.KeyStoreException;
import java.security.cert.X509Certificate;

import java.security.KeyStore;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.Security;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

public class Test  
{
   public static void  main(String arg[]) throws Exception
   {
       try
       {   
         //Create our certificates from our CAC Card
         String configName = "card.config";
         Provider p = new sun.security.pkcs11.SunPKCS11(configName);
         Security.addProvider(p);

         //Get the pin from user entered data
         Console c = System.console();
         char[] pin = c.readPassword("Enter your PIN: ");
         KeyStore cac = null;

         cac = KeyStore.getInstance("PKCS11");
         cac.load(null, pin);

         showInfoAboutCAC(cac);

      }
      catch(Exception ex)
      {
         //System.out.println("*" + ex.getMessage());
         ex.printStackTrace();
         System.exit(0);
      }
   }

   public static void showInfoAboutCAC(KeyStore ks) throws KeyStoreException, CertificateException
   {
      Enumeration<String> aliases = ks.aliases();

      while (aliases.hasMoreElements()) 
      {
         String alias = aliases.nextElement();
         X509Certificate[] cchain = (X509Certificate[]) ks.getCertificateChain(alias);

         System.out.println("Certificate Chain for : " + alias);
         for (int i = 0; i < cchain.length; i ++)
         {
            System.out.println(i + " SubjectDN: " + cchain[i].getSubjectDN());
            System.out.println(i + " IssuerDN:  " + cchain[i].getIssuerDN());
         }
      }
   }
}

此时,您拥有一个密钥库,可用于创建 ssl 套接字以与https 网络服务器。

You need to create a file called card.config and include the following lines in it:

name = myConfig
library = /path/to/library/that/implements/cac/card/reader 

And then try this:

import java.io.*;
import java.util.*;

import java.security.cert.CertificateException;
import java.security.KeyStoreException;
import java.security.cert.X509Certificate;

import java.security.KeyStore;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.Security;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

public class Test  
{
   public static void  main(String arg[]) throws Exception
   {
       try
       {   
         //Create our certificates from our CAC Card
         String configName = "card.config";
         Provider p = new sun.security.pkcs11.SunPKCS11(configName);
         Security.addProvider(p);

         //Get the pin from user entered data
         Console c = System.console();
         char[] pin = c.readPassword("Enter your PIN: ");
         KeyStore cac = null;

         cac = KeyStore.getInstance("PKCS11");
         cac.load(null, pin);

         showInfoAboutCAC(cac);

      }
      catch(Exception ex)
      {
         //System.out.println("*" + ex.getMessage());
         ex.printStackTrace();
         System.exit(0);
      }
   }

   public static void showInfoAboutCAC(KeyStore ks) throws KeyStoreException, CertificateException
   {
      Enumeration<String> aliases = ks.aliases();

      while (aliases.hasMoreElements()) 
      {
         String alias = aliases.nextElement();
         X509Certificate[] cchain = (X509Certificate[]) ks.getCertificateChain(alias);

         System.out.println("Certificate Chain for : " + alias);
         for (int i = 0; i < cchain.length; i ++)
         {
            System.out.println(i + " SubjectDN: " + cchain[i].getSubjectDN());
            System.out.println(i + " IssuerDN:  " + cchain[i].getIssuerDN());
         }
      }
   }
}

At this point you have a keystore that you can use to create the ssl socket to talk to the https web server.

空名2024-07-21 08:05:34

研究使用 SSO 类型应用程序(例如 OpenSSOJOSSO。 代理应该更容易嵌入,并且他们已经实现了大部分细节。 如果您需要自己执行此操作,他们还有很多与所需步骤相关的文档,例如: 数字证书设置

Look into using cert authentication using an SSO type application such as OpenSSO or JOSSO. The agent should be simpler to embed, and they have already implemented most of the details. If you need to do it yourself, they also have a lot of documentation related to the steps needed such as: digital certificates setup

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文