C#Java間でRSA暗号解読インタラクションを行う
7119 ワード
ここで、RSAアルゴリズムの復号化がC#とJavaの間でやり取りされている問題についてお話ししますが、この2、3日悩んでいて、他の人が書いた文章もたくさん見て、とても役に立ちましたが、私の実際の問題を解決することができず、ついに、私に壊されました.
まず、このコードを書く目的を紹介します:webService検証の問題を完成して、サーバー側はC#開発を採用して、クライアントはJava開発を採用します.サーバ側はクライアントに公開鍵を提供し、すでにデータ暗号化を行い、クライアントが暗号化した後、データをサーバに提出し、サーバは秘密鍵でデータを復号し、検証を行う.
ここで遭遇する主な問題はC#RSACryptoServiceProviderクラスで発生する公開鍵、秘密鍵はxml文字列データであり、java RSAアルゴリズムで要求されるModulus、ExponentはBigIntegerタイプであり、両者の間の変換が問題である.
JavaとC#がそれぞれ独立してRSA暗号解読を行うことについて、java RSA暗号解読実装()とC#におけるRSA暗号解読と署名と検証の実装の2つの文章を見ることができます.
次に、実装手順について説明します.
まずC#RSACryptoServiceProviderクラスから公開鍵、秘密鍵を生成
ここで生成される公開鍵は
クライアント(Java)でC#に提供される公開鍵抽出ModulusとExponent
ModulusとExponentで公開鍵RSAPublicKey(java)を生成
ここで重要なステップは、まずMudolusとExponentをBase 64復号することである.これは、C#が生成した鍵ペアのためであり、そのパラメータはBase 64を介してStringタイプに符号化され、java RSAパラメータはbase 64を介して符号化されていないbyte[]タイプである.
Base 64の符号化、復号方法については、この記事を参照してjavaの符号化と復号化について詳しく考えたい.
公開鍵を取得するとRSA暗号化処理を行うことができるが、ここでさらに、RSA暗号化復号には最大長制限があり、暗号化最大長は117バイト、復号最大長は128バイトである.また、ここで暗号化したデータはBase 64符号化処理によって処理される
暗号化されたデータはC#サーバ側に提出して復号します.もちろん、ここでも最大長制限の問題に注意してください.
これで、無事完成しました.
テストを経て、このようにして確かに正しい結果を得た.
何か問題があれば,皆さんのご指摘をお待ちしております.
----------------------------------------------------------------------------------------
C#Java間でRSA暗号解読インタラクションを行う(二)
C#Java間でRSA暗号解読インタラクションを行う(三)
まず、このコードを書く目的を紹介します:webService検証の問題を完成して、サーバー側はC#開発を採用して、クライアントはJava開発を採用します.サーバ側はクライアントに公開鍵を提供し、すでにデータ暗号化を行い、クライアントが暗号化した後、データをサーバに提出し、サーバは秘密鍵でデータを復号し、検証を行う.
ここで遭遇する主な問題はC#RSACryptoServiceProviderクラスで発生する公開鍵、秘密鍵はxml文字列データであり、java RSAアルゴリズムで要求されるModulus、ExponentはBigIntegerタイプであり、両者の間の変換が問題である.
JavaとC#がそれぞれ独立してRSA暗号解読を行うことについて、java RSA暗号解読実装()とC#におけるRSA暗号解読と署名と検証の実装の2つの文章を見ることができます.
次に、実装手順について説明します.
まずC#RSACryptoServiceProviderクラスから公開鍵、秘密鍵を生成
///
/// 、
///
/// 、 , "PUBLIC", "PRIVATE"
public Dictionary createKeyPair()
{
Dictionary keyPair = new Dictionary();
RSACryptoServiceProvider provider = new RSACryptoServiceProvider(1024);
keyPair.Add("PUBLIC", provider.ToXmlString(false));
keyPair.Add("PRIVATE", provider.ToXmlString(true));
return keyPair;
}
ここで生成される公開鍵は
t+56m5jXXonAJAKC7mgkhAZX5gWJTZojbSloLpLBGEWiebFaM+aUUKALfRx83/HaUV79ZiR3zuLJOLBdALx1cmcPk/b9fdNblLmzqi4cfSnfmMLWh05xf+ZS1pKHSKQtui3dfuu+3XH6Ak+S38dpIZUj/hihQQuKysN6GJ9h+c8=
AQAB
クライアント(Java)でC#に提供される公開鍵抽出ModulusとExponent
/**
* modulus exponent haspMap
* @return
* @throws MalformedURLException
* @throws DocumentException
*/
public static HashMap rsaParameters(String xmlPublicKey) throws MalformedURLException, DocumentException{
HashMap map = new HashMap();
Document doc = DocumentHelper.parseText(xmlPublicKey);
String mudulus = (String) doc.getRootElement().element("Modulus").getData();
String exponent = (String) doc.getRootElement().element("Exponent").getData();
map.put("mudulus", mudulus);
map.put("exponent", exponent);
return map;
}
ModulusとExponentで公開鍵RSAPublicKey(java)を生成
ここで重要なステップは、まずMudolusとExponentをBase 64復号することである.これは、C#が生成した鍵ペアのためであり、そのパラメータはBase 64を介してStringタイプに符号化され、java RSAパラメータはbase 64を介して符号化されていないbyte[]タイプである.
Base 64の符号化、復号方法については、この記事を参照してjavaの符号化と復号化について詳しく考えたい.
public static byte[] decodeBase64(String input) throws Exception{
Class clazz=Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");
Method mainMethod= clazz.getMethod("decode", String.class);
mainMethod.setAccessible(true);
Object retObj=mainMethod.invoke(null, input);
return (byte[])retObj;
}
/**
* RSA
* @param modules
* @param exponent
* @return
*/
public static PublicKey getPublicKey(String modulus, String exponent){
try {
byte[] m = decodeBase64(modulus);
byte[] e = decodeBase64(exponent);
BigInteger b1 = new BigInteger(1,m);
BigInteger b2 = new BigInteger(1,e);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
公開鍵を取得するとRSA暗号化処理を行うことができるが、ここでさらに、RSA暗号化復号には最大長制限があり、暗号化最大長は117バイト、復号最大長は128バイトである.また、ここで暗号化したデータはBase 64符号化処理によって処理される
public static String encrypt(byte[] source, PublicKey publicKey) throws Exception {
String encryptData ="";
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
int length = source.length;
int offset = 0;
byte[] cache;
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
int i = 0;
while(length - offset > 0){
if(length - offset > MAXENCRYPTSIZE){
cache = cipher.doFinal(source, offset, MAXENCRYPTSIZE);
}else{
cache = cipher.doFinal(source, offset, length - offset);
}
outStream.write(cache, 0, cache.length);
i++;
offset = i * MAXENCRYPTSIZE;
}
return encodeBase64(outStream.toByteArray());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return encryptData;
}
暗号化されたデータはC#サーバ側に提出して復号します.もちろん、ここでも最大長制限の問題に注意してください.
///
/// RSA
///
/// Base64
///
/// RSA
public static string decrypt(string encryptData, string privateKey)
{
string decryptData = "";
try
{
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.FromXmlString(privateKey);
byte[] bEncrypt = Convert.FromBase64String(encryptData);
int length = bEncrypt.Length;
int offset = 0;
string cache ;
int i = 0;
while (length - offset > 0)
{
if (length - offset > MAXDECRYPTSIZE)
{
cache = Encoding.UTF8.GetString(provider.Decrypt(getSplit(bEncrypt, offset, MAXDECRYPTSIZE), false));
}
else
{
cache = Encoding.UTF8.GetString(provider.Decrypt(getSplit(bEncrypt, offset, length - offset), false));
}
decryptData += cache;
i++;
offset = i*MAXDECRYPTSIZE;
}
}
catch(Exception e)
{
throw e;
}
return decryptData;
}
///
///
///
///
///
///
///
private static byte[] getSplit(byte[] input, int offset, int length)
{
byte[] output = new byte[length];
for (int i = offset; i < offset + length; i++)
{
output[i - offset] = input[i];
}
return output;
}
これで、無事完成しました.
テストを経て、このようにして確かに正しい結果を得た.
何か問題があれば,皆さんのご指摘をお待ちしております.
----------------------------------------------------------------------------------------
C#Java間でRSA暗号解読インタラクションを行う(二)
C#Java間でRSA暗号解読インタラクションを行う(三)