Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Ошибка при подписании текста, с помощью Java


Автор: fclmfan 18.4.2011, 11:50
Здравствуйте! Значит, описание проблемы:
Сгенерировал keystore-файл с помощью keytool. Загрузил его содержимое в поле типа blob, в Oracle. Далее, на базе есть такой Java Source:
Код

create or replace and compile java source named digitalsignature as
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import oracle.sql.BLOB;
import java.sql.SQLException;

public class DigitalSignature implements Serializable {

    private KeyPairGenerator keyPairGenerator;   // Генератор ключевых пар
    private KeyPair keyPair;                     // Пара ключей
    private PrivateKey privateKey;               // Приватный ключ
    private PublicKey publicKey;                 // Открытый ключ
    private Signature signature;                 // Цифровая подпсь
    private byte[] realSign;

    /**
     * Конструктор класса <code>SigningMessage</code> используется тогда, когда имеется пара
     * ключей, и они находится в сертификате, и в хранилище ключей
     * @param signAlg - алгоритм ключевой подписи. Пример - SHA1withDSA, DSA, RSA и пр.
     * @param provName - название крипто провайдера. Пример - SUN и пр (Если нет необходимости в явном
     * указании крипто провайдера, можно указать null)
     * @throws NullPointerException
     * @throws NoSuchAlgorithmException
     * @throws NoSuchProviderException
     */
    public DigitalSignature(String signAlg, String provName) throws NullPointerException,
                                                                    NoSuchAlgorithmException, NoSuchProviderException {
        if (signAlg == null) {
            throw new NullPointerException();
        } else {
            if (provName == null) {
                signature = Signature.getInstance(signAlg);
            } else {
                signature = Signature.getInstance(signAlg, provName);
            }
        }
    }

    /**
     * Метод <code>signingMessage</code> создает цифровую подпись из указаного открытого текста
     * @param msg - Открытый текст
     * @throws InvalidKeyException
     * @throws SignatureException
     */
    public void signingMessage(String msg) throws InvalidKeyException, SignatureException {
        if (msg == null) {
            throw new NullPointerException();
        }

        //Set private key
        if (privateKey == null) {
            throw new IllegalArgumentException();
        }

        signature.initSign(privateKey);
        signature.update(msg.getBytes());
        realSign = signature.sign();
    }

    /**
     * Метод verifyMessage проверяет действительность цифровой подписи
     * @param msg - Открытый текст
     * @param sgn - Текст с цифровой подписью
     * @return - Возвращает результат проверки цифровой подписи
     * @throws InvalidKeyException
     * @throws SignatureException
     */
    public boolean verifyMessage(String msg, String sgn) throws InvalidKeyException, SignatureException {
        if ((msg == null) || (sgn == null)) {
            throw new NullPointerException();
        }

        //Verifying message
        signature.initVerify(publicKey);
        signature.update(msg.getBytes());

        boolean result = signature.verify(sgn.getBytes());
        return result;
    }

    /**
     * Метод <code>getSign</code> возвращает цифровую подпись как массив байтов
     * @return Цифровую подпись
     */
    public byte[] getSign() {
        return realSign;
    }

    /**
     * Метод <code>readPrivateKey</code> считывает файл из указанного потока
     * @param fRead - потока ввода
     * @return Возвращает приватный ключ из заданого потока ввода
     * @throws NullPointerException
     * @throws IOException
     * @throws ClassNotFoundException
     * @throws ClassCastException
     */
    public PrivateKey readPrivateKey(FileInputStream fRead) throws NullPointerException, IOException,
                                                                   ClassNotFoundException, ClassCastException {
        if (fRead == null) {
            throw new NullPointerException();
        } else {
            ObjectInputStream obRead = new ObjectInputStream(fRead);
            Object ob = obRead.readObject();
            if (ob instanceof PrivateKey) {
                PrivateKey privKey = (PrivateKey)ob;
                return privKey;
            } else {
                throw new ClassCastException();
            }
        }
    }

    /**
     * Метод <code>readPublicKey</code> считывает открытый ключ из указанного потока ввода
     * @param fRead - поток ввода
     * @return Открытый ключ
     * @throws IOException
     * @throws ClassNotFoundException
     * @throws ClassCastException
     */
    public PublicKey readPublicKey(FileInputStream fRead) throws IOException, ClassNotFoundException, ClassCastException {

        if (fRead == null) {
            throw new NullPointerException();
        } else {
            ObjectInputStream obRead = new ObjectInputStream(fRead);
            Object ob = obRead.readObject();
            if (ob instanceof PublicKey) {
                PublicKey privKey = (PublicKey)ob;
                return privKey;
            } else {
                throw new ClassCastException();
            }
        }
    }

    /**
     * Метод <code>getPair</code> возвращает пару ключей из хранилища ключей и сертификата открытого ключа
     * @param in            - поток ввода, где находится хранилише
     * @param alias         - название сертификата открытого ключа
     * @param passKeyStore  - пароль для хранилища ключей
     * @param passAlias     - пароль для сертификата
     * @return Метод возвращает пару ключей
     * @throws KeyStoreException
     * @throws IOException
     * @throws CertificateException
     * @throws NoSuchAlgorithmException
     * @throws UnrecoverableEntryException
     */
    public KeyPair getPair(BLOB in, String alias, String passKeyStore, String passAlias) throws KeyStoreException, IOException,
                                                                                                CertificateException,
                                                                                                NoSuchAlgorithmException,
                                                                                                UnrecoverableKeyException, SQLException {
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(in.asciiStreamValue(), passKeyStore.toCharArray());
        Key key = ks.getKey(alias, passAlias.toCharArray());
        if (key instanceof PrivateKey) {
            // Get certificate of public key
            Certificate cert = ks.getCertificate(alias);
            PublicKey publicKey = cert.getPublicKey();
            return new KeyPair(publicKey, (PrivateKey)key);
        }
        return null;
    }
    
    public static String signText(BLOB in, String alias, String passKeyStore, String passAlias, String msg) throws KeyStoreException,
                                                                                                                   NullPointerException,
                                                                                                                   NoSuchAlgorithmException,
                                                                                                                   NoSuchProviderException,
                                                                                                                   IOException,
                                                                                                                   CertificateException,
                                                                                                                   UnrecoverableKeyException,
                                                                                                                   SQLException,
                                                                                                                   InvalidKeyException,
                                                                                                                   SignatureException {
        DigitalSignature ms = new DigitalSignature("DSA", null);
        KeyPair kp = ms.getPair(in, "rinat", "secret", "secret");
        PrivateKey privateKey = kp.getPrivate();
        ms.setPrivateKey(privateKey);
        ms.signingMessage(msg);
        return new String(ms.getSign());
    }

    /**
     * Метод <code>setPrivateKey</code> устанавливает приватный ключ пользователя
     * @param prk - приватный пользователя
     */
    public void setPrivateKey(PrivateKey prk) {
        privateKey = prk;
    }

    /**
     * Метод <code>getPrivateKey</code> возвращает приватный ключ пользователя
     * @return Приватный ключ
     */
    public PrivateKey getPrivateKey() {
        return privateKey;
    }

    /**
     * Метод <code>setPublicKey</code> устанавливает открытый ключ пользователя
     * @param pbk - Открытый ключ
     */
    public void setPublicKey(PublicKey pbk) {
        publicKey = pbk;
    }

    /**
     * Метод <code>getPublicKey</code> возвращает открытый ключ пользователя
     * @return Открытый ключ
     */
    public PublicKey getPublicKey() {
        return publicKey;
    }

}


ещё создал функцию:
Код

create or replace function signText( iKeyStore       in BLOB
                                   , iAlias          in varchar2
                                   , ipassKeyStore   in varchar2
                                   , ipassAlias      in varchar2
                                   , imsg            in varchar2
                                   ) return varchar2
as
  language java name 'DigitalSignature.signText( oracle.sql.BLOB
                                               , java.lang.String
                                               , java.lang.String
                                               , java.lang.String
                                               , java.lang.String
                                               ) return java.lang.String';



вызываю эту функцию:
Код

declare 
  vKeyStore blob;
  result    varchar2(4000);
begin
  select t.text into vKeyStore from temp t where rownum = 1;
  -- Call the function
  result := signtext(vKeyStore, 'myname', 'secret', 'secret', 'Test');
  dbms_output.put_line(result);
end;


выдаёт ошибку:
Код

ORA-29532: Java call terminated by uncaught Java exception: java.io.IOException: Invalid keystore format
ORA-06512: at "MY_SCHEME.SIGNTEXT", line 1
ORA-06512: at line 6


хотя, я тестировал на клиентской части этот же класс, только вместо blob там был FileInputStream, всё отработало. Подумал, может как-то неправильно загрузил keystore в blob? Выгрузил его обратно в файл, использовал на клиентской части, отработало нормально.
Помогите разобраться плиз.

Автор: LSD 18.4.2011, 17:58
Замени asciiStreamValue() на getBinaryStream().

Автор: fclmfan 18.4.2011, 18:48
вау! smile  спасибо! блин как это я упустил smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)