私の仕事は次のとおりです。
output.dat
というファイルにデジタル署名の出力を保存します。以下のプログラムはエラーをスローしています:「Java.security.InvalidKeyException:このキーをサポートするインストール済みプロバイダーはありません:Sun.security.provider.DSAPublicKeyImpl」。
import Java.security.*;
import Java.security.KeyStore.*;
import Java.io.*;
import Java.security.PublicKey;
import Java.security.PrivateKey;
import javax.crypto.Cipher;
import Java.nio.charset.*;
import Sun.security.provider.*;
import javax.crypto.*;
public class Code {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
try {
/* getting data for keystore */
File file = new File(System.getProperty("user.home") + File.separatorChar + ".keystore");
FileInputStream is = new FileInputStream(file);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
/*Information for certificate to be generated */
String password = "abcde";
String alias = "mykeys";
String alias1 = "skeys";
String filepath ="C:\\email.txt";
/* getting the key*/
keystore.load(is, password.toCharArray());
PrivateKey key = (PrivateKey)keystore.getKey(alias, "bemylife".toCharArray());
//PrivateKey key = cert1.getPrivateKey();
//PublicKey key1= (PrivateKey)key;
/* Get certificate of public key */
Java.security.cert.Certificate cert = keystore.getCertificate(alias);
/* Here it prints the public key*/
System.out.println("Public Key:");
System.out.println(cert.getPublicKey());
/* Here it prints the private key*/
System.out.println("\nPrivate Key:");
System.out.println(key);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE,cert.getPublicKey());
String cleartextFile = "C:\\email.txt";
String ciphertextFile = "D:\\ciphertextRSA.png";
FileInputStream fis = new FileInputStream(cleartextFile);
FileOutputStream fos = new FileOutputStream(ciphertextFile);
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
byte[] block = new byte[32];
int i;
while ((i = fis.read(block)) != -1) {
cos.write(block, 0, i);
}
cos.close();
/* computing the signature*/
Signature dsa = Signature.getInstance("SHA1withDSA", "Sun");
dsa.initSign(key);
FileInputStream f = new FileInputStream(ciphertextFile);
BufferedInputStream in = new BufferedInputStream(f);
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) >= 0) {
dsa.update(buffer, 0, len);
};
in.close();
/* Here it prints the signature*/
System.out.println("Digital Signature :");
System.out.println( dsa.sign());
/* Now Exporting Certificate */
System.out.println("Exporting Certificate. ");
byte[] buffer_out = cert.getEncoded();
FileOutputStream os = new FileOutputStream(new File("d:\\signedcetificate.cer"));
os.write(buffer_out);
os.close();
/* writing signature to output.dat file */
byte[] buffer_out1 = dsa.sign();
FileOutputStream os1 = new FileOutputStream(new File("d:\\output.dat"));
os1.write(buffer_out1);
os1.close();
} catch (Exception e) {System.out.println(e);}
}
}
問題は、DSAキーがRSA暗号化に適していないことです。暗号化にはRSAキーが必要です。2つのキーが不要になるように、署名アルゴリズムをRSA/SHA1に切り替えることができます。
キーストアファイル(おそらく.jks
で終わる)から Java.security.KeyStore オブジェクトに読み込む必要があります。
/**
* Reads a Java keystore from a file.
*
* @param keystoreFile
* keystore file to read
* @param password
* password for the keystore file
* @param keyStoreType
* type of keystore, e.g., JKS or PKCS12
* @return the keystore object
* @throws KeyStoreException
* if the type of KeyStore could not be created
* @throws IOException
* if the keystore could not be loaded
* @throws NoSuchAlgorithmException
* if the algorithm used to check the integrity of the keystore
* cannot be found
* @throws CertificateException
* if any of the certificates in the keystore could not be loaded
*/
public static KeyStore loadKeyStore(final File keystoreFile,
final String password, final String keyStoreType)
throws KeyStoreException, IOException, NoSuchAlgorithmException,
CertificateException {
if (null == keystoreFile) {
throw new IllegalArgumentException("Keystore url may not be null");
}
LOG.debug("Initializing key store: {}", keystoreFile.getAbsolutePath());
final URI keystoreUri = keystoreFile.toURI();
final URL keystoreUrl = keystoreUri.toURL();
final KeyStore keystore = KeyStore.getInstance(keyStoreType);
InputStream is = null;
try {
is = keystoreUrl.openStream();
keystore.load(is, null == password ? null : password.toCharArray());
LOG.debug("Loaded key store");
} finally {
if (null != is) {
is.close();
}
}
return keystore;
}
KeyStore
を取得したら、Certificate
および公開キーと秘密キーにアクセスできます。
しかし、それを使用してテキストに署名し、ファイルに保存することはより複雑で、間違いを犯しやすいです。 指定された公開キーを使用して文字列に署名する を見て、getKeyPair
メソッドをKeyStore
を使用するメソッドに置き換えます。の線に沿って何か
public static KeyPair getKeyPair(final KeyStore keystore,
final String alias, final String password) {
final Key key = (PrivateKey) keystore.getKey(alias, password.toCharArray());
final Certificate cert = keystore.getCertificate(alias);
final PublicKey publicKey = cert.getPublicKey();
return KeyPair(publicKey, (PrivateKey) key);
}
(明らかに少し荒い、私は便利なサンプルを持っていませんでした)
Javaコードは脳の上部に保存されていませんが、いくつかの一般的な健全性チェックは次のとおりです。
必要な場所に保存するパブリック証明書はありますか?特に、私の記憶では、公開鍵と秘密鍵を持つ証明書は単一のエイリアスの下に一緒に格納されるため、そこにある2つのエイリアス設定は本当に奇妙に思えます。両方を同じエイリアスの下に保存し、秘密鍵呼び出しと公開鍵呼び出しの両方でそれを参照してみてください。
証明書から何か他のものを取得できますか。たとえば、サブジェクトDNまたは発行者DNは両方とも証明書の必須フィールドです。これにより、証明書が予想どおりに読み取られていることを証明できます。
ほとんどすべての暗号化トランザクションでは、ファイルからの読み取り方法とエンコード方法の転送方法に非常に注意してください。 File IOを作成し、奇妙な方法でそこから引き出した場合、キーマテリアルのエンコーディングを破損する可能性があります。これは最後に確認することです-通常JavaとJKSはそれほど悪いことではありませんが、実際にはファイルの形式について明確にしてください-たとえば、JKSファイルはPKCS 12ファイルとは異なります。
trusted.load(in, ((PBCApplication) context.getApplicationContext()).getBuildSettings().getCertificatePass());
Enumeration enumeration = trusted.aliases();
while (enumeration.hasMoreElements()) {
String alias = (String) enumeration.nextElement();
System.out.println("alias name: " + alias);
Certificate certificate = trusted.getCertificate(alias);
certificate.getPublicKey();
}