Page tree

Для работы с токенами в Java разработана специальная библиотека-обертка pkcs11jna. Эта обертка предоставляет интерфейс над динамическими PKCS#11 библиотеками.
Исходный код расположен на: https://github.com/AktivCo/pkcs11jna


Работа с библиотекой pkcs11jna достаточно проста. С помощью net.java.dev.jna нужно загрузить PKCS#11 библиотеку и далее работать с возвращенным объектом по интерфейсу класса RtPkcs11:

RtPkcs11
import com.sun.jna.Native;
import ru.rutoken.pkcs11jna.RtPkcs11;

RtPkcs11 rtpkcs11 = Native.load(Native.extractFromResourcePath("rtpkcs11ecp").getAbsolutePath(), RtPkcs11.class);


Класс RtPkcs11 предоставляет интерфейс над PKCS#11 функциям обернутой библиотекой. Для примера покажем, как можно проинициализировать токен:

Пример инициализации токена
import com.sun.jna.NativeLong;
import com.sun.jna.Native;
import com.sun.jna.ptr.NativeLongByReference;
import ru.rutoken.pkcs11jna.CK_C_INITIALIZE_ARGS;
import ru.rutoken.pkcs11jna.Pkcs11Constants;
import ru.rutoken.pkcs11jna.RtPkcs11;

public class Init {
    private final static byte[] TOKEN_LABEL = {'M', 'y', ' ', 'R', 'u', 't', 'o', 'k',
            'e', 'n', ' ', ' ', ' ', ' ', ' ', ' ',
            ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
            ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};

    public final static CK_C_INITIALIZE_ARGS INITIALIZE_ARGUMENTS =
            new CK_C_INITIALIZE_ARGS(null, null, null, null, new NativeLong(Pkcs11Constants.CKF_OS_LOCKING_OK), null);


    public static final byte[] DEFAULT_USER_PIN = {'1', '2', '3', '4', '5', '6', '7', '8'};
    public static final byte[] DEFAULT_SO_PIN = {'8', '7', '6', '5', '4', '3', '2', '1'};
    
    public static void main(String[] args) {
        NativeLong hSession = new NativeLong(Pkcs11Constants.CK_INVALID_HANDLE);
        RtPkcs11 rtpkcs11 = null;
        
        
        try {
            System.out.println("Example of token initialization using rtpkcs11ecp via JNA");
            rtpkcs11 = Native.load(Native.extractFromResourcePath("rtpkcs11ecp").getAbsolutePath(), RtPkcs11.class);

            System.out.println("Library initialization and acquiring of function list");
            NativeLong rv = rtpkcs11.C_Initialize(INITIALIZE_ARGUMENTS);

            if (!Pkcs11Constants.equalsPkcsRV(Pkcs11Constants.CKR_OK, rv)) {
                throw new Exception("C_Initialize failed");
            }

            System.out.println("Acquiring list of slots with connected tokens");

            NativeLongByReference slotsCount = new NativeLongByReference();
            rv = rtpkcs11.C_GetSlotList(Pkcs11Constants.CK_TRUE, null, slotsCount);
            if (!Pkcs11Constants.equalsPkcsRV(Pkcs11Constants.CKR_OK, rv)) throw new Exception("C_GetSlotList failed");
            
            
            if (slotsCount.getValue().intValue() == 0) {
                throw new Exception("No Rutoken is available!");
            }

            NativeLong[] pSlotList = new NativeLong[slotsCount.getValue().intValue()];
            rv = rtpkcs11.C_GetSlotList(Pkcs11Constants.CK_TRUE, pSlotList, slotsCount);
            if (!Pkcs11Constants.equalsPkcsRV(Pkcs11Constants.CKR_OK, rv)) throw new Exception("C_GetSlotList failed");

            System.out.println("Token initialization");
            rv = rtpkcs11.C_InitToken(pSlotList[0], DEFAULT_SO_PIN, new NativeLong(DEFAULT_SO_PIN.length), TOKEN_LABEL);
            if (!Pkcs11Constants.equalsPkcsRV(Pkcs11Constants.CKR_OK, rv)) throw new Exception("C_GetSlotList failed");

            System.out.println("Opening session");
            NativeLongByReference phSession = new NativeLongByReference();
            rv = rtpkcs11.C_OpenSession(pSlotList[0],
                    new NativeLong(Pkcs11Constants.CKF_SERIAL_SESSION | Pkcs11Constants.CKF_RW_SESSION),
                    null, null, phSession);
            if (!Pkcs11Constants.equalsPkcsRV(Pkcs11Constants.CKR_OK, rv)) throw new Exception("C_GetSlotList failed");
            
            hSession = phSession.getValue();

            System.out.println("Logging in as administrator");
            rv = rtpkcs11.C_Login(hSession, new NativeLong(Pkcs11Constants.CKU_SO), DEFAULT_SO_PIN, new NativeLong(DEFAULT_SO_PIN.length));
            if (!Pkcs11Constants.equalsPkcsRV(Pkcs11Constants.CKR_OK, rv)) throw new Exception("C_GetSlotList failed");

            System.out.println("User PIN initialization");
            rv = rtpkcs11.C_InitPIN(hSession, DEFAULT_USER_PIN, new NativeLong(DEFAULT_USER_PIN.length));
            if (!Pkcs11Constants.equalsPkcsRV(Pkcs11Constants.CKR_OK, rv)) throw new Exception("C_GetSlotList failed");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
            if (rtpkcs11 != null) {
                System.out.println("Logging out");
                NativeLong rv = rtpkcs11.C_Logout(hSession);

                System.out.println("Closing session");
                rv = rtpkcs11.C_CloseSession(hSession);

                System.out.println("Finalizing PKCS11 library");
                rv = rtpkcs11.C_Finalize(null);

                System.out.println("Test has been completed.");
            }
        }
    }
}


Больше примеров по работе с библиотекой pkcs11jna можно найти в Рутокен SDK в директории sdk/java/samples.


  • No labels