그냥 닦으세요. 아래의 코드는 여전히 약간 지저분하지만 그래도 작동 할 수있는 것 같습니다.
우리는 Windows의 메시지가 여기에 설명되어 해독하는 공개 키를 사용할 수없는 이유 : 그것을, 이 http://www.derkeiler.com/Newsgroups/microsoft.public.dotnet.security/2004-05/0270.html
다음, 당신이 어딘가에, C# 코드의 공개 키 계수와 지수를 필요로 할 파일 또는 임베디드는 실제로 여기의 문제가 아닙니다. Base64를 사용하여 이진 키를 마무리합니다. Windows가 실제로 가져올 키를 생성하는 것을 포기했습니다. 게다가, 내가 필요로하는 것을 위해 공개 키는 임베디드 리소스가 될 것입니다.
내가 가진 마지막 문제는 키에서 생성 된 계수가 Windows (C#)에서 작동하지 않는다는 것입니다. 이 StackOverflow 포스트는 Windows의 모듈이 앞에 0을 포함 할 수 없다는 것을 해결하기위한 열쇠를 가졌습니다. Android in-app billing Verification of Receipt in Dot Net(C#)
Java에서 생성 된 계수는 C#에서 작동하지 않았습니다. 작업 공개 키 계수 만들기 위해 해당 게시물에서 stripLeadingZeros 코드를 사용
$ openssl genrsa -out private_key.pem 2048
$ openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key.pem -out private_key.der -nocrypt
$ openssl rsa -in private_key.pem -pubout -outform DER -out public_key.der
자바 코드 :
우선 들어
private static byte[] stripLeadingZeros(byte[] a) {
int lastZero = -1;
for (int i = 0; i < a.length; i++) {
if (a[i] == 0) {
lastZero = i;
}
else {
break;
}
}
lastZero++;
byte[] result = new byte[a.length - lastZero];
System.arraycopy(a, lastZero, result, 0, result.length);
return result;
}
를이 내가 키 파일을 생성하는 방법이다
package com.example.signing;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import jcifs.util.Base64;
public class SigningExample {
private static String PRIVATE_KEY_FILE = "private_key.der";
private static String PUBLIC_KEY_FILE = "public_key.der";
/**
* @param args
*/
public static void main(String[] args) {
SigningExample.sign();
}
private static void sign() {
try {
String text = new String(SigningExample.loadFromFile("message.xml"));
String message = Base64.encode(text.getBytes());
RSAPrivateKey privateKey = PrivateRSAKeyReader.getKeyFile(SigningExample.PRIVATE_KEY_FILE);
RSAPublicKey publicKey = PublicRSAKeyReader.getKeyFile(SigningExample.PUBLIC_KEY_FILE);
byte[] modulusBytes = publicKey.getModulus().toByteArray();
byte[] exponentBytes = publicKey.getPublicExponent().toByteArray();
modulusBytes = SigningExample.stripLeadingZeros(modulusBytes);
String modulusB64 = Base64.encode(modulusBytes);
String exponentB64 = Base64.encode(exponentBytes);
System.out.println("Copy these two into your c# code:");
System.out.println("DotNet Modulus : " + modulusB64);
System.out.println("DotNet Exponent: " + exponentB64);
// Testing
byte[] signature = SigningExample.sign(message.getBytes(), privateKey, "SHA1withRSA");
String signedMessage = message + "\n" + Base64.encode(signature);
SigningExample.saveToBase64File("message.signed", signedMessage.getBytes());
System.out.println("\nMessage :\n" + signedMessage);
String[] newkey = new String(SigningExample.loadFromBase64File("message.signed")).split("\\n");
System.out.println("Verified : " + SigningExample.verify(newkey[0].getBytes(), publicKey, "SHA1withRSA", Base64.decode(newkey[1])));
} catch (Exception e) {
e.printStackTrace();
}
}
private static byte[] stripLeadingZeros(byte[] a) {
int lastZero = -1;
for (int i = 0; i < a.length; i++) {
if (a[i] == 0) {
lastZero = i;
} else {
break;
}
}
lastZero++;
byte[] result = new byte[a.length - lastZero];
System.arraycopy(a, lastZero, result, 0, result.length);
return result;
}
private static byte[] sign(byte[] data, PrivateKey prvKey,
String sigAlg) throws Exception {
Signature sig = Signature.getInstance(sigAlg);
sig.initSign(prvKey);
sig.update(data, 0, data.length);
return sig.sign();
}
private static boolean verify(byte[] data, PublicKey pubKey,
String sigAlg, byte[] sigbytes) throws Exception {
Signature sig = Signature.getInstance(sigAlg);
sig.initVerify(pubKey);
sig.update(data, 0, data.length);
return sig.verify(sigbytes);
}
public static void saveToBase64File(String fileName, byte[] data) throws IOException {
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(fileName));
try {
String b64 = Base64.encode(data);
int lineLength = 64;
int idx = 0;
int len = b64.length();
while (len - idx >= lineLength) {
out.write(b64.substring(idx, idx + lineLength).getBytes());
out.write('\n');
idx += lineLength;
}
out.write(b64.substring(idx, len).getBytes());
} catch (Exception e) {
throw new IOException("Unexpected error", e);
} finally {
out.close();
}
}
public static byte[] loadFromBase64File(String fileName) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(fileName));
try {
StringBuffer sb = new StringBuffer();
String buffer;
while ((buffer = br.readLine()) != null) {
sb.append(buffer);
}
return Base64.decode(sb.toString());
} catch (Exception e) {
throw new IOException("Unexpected error", e);
} finally {
br.close();
}
}
public static void saveToFile(String fileName, byte[] data) throws IOException {
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(fileName));
try {
out.write(data);
} catch (Exception e) {
throw new IOException("Unexpected error", e);
} finally {
out.close();
}
}
public static byte[] loadFromFile(String fileName) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(fileName));
try {
StringBuffer sb = new StringBuffer();
String buffer;
while ((buffer = br.readLine()) != null) {
sb.append(buffer);
}
return sb.toString().getBytes();
} catch (Exception e) {
throw new IOException("Unexpected error", e);
} finally {
br.close();
}
}
}
class PrivateRSAKeyReader {
public static RSAPrivateKey getKeyFile(String filename) throws Exception {
File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int) f.length()];
dis.readFully(keyBytes);
dis.close();
return PrivateRSAKeyReader.generateKey(keyBytes);
}
public static RSAPrivateKey getKey(String base64) throws Exception {
byte[] keyBytes = Base64.decode(base64);
return PrivateRSAKeyReader.generateKey(keyBytes);
}
private static RSAPrivateKey generateKey(byte[] keyBytes) throws Exception {
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
return (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(spec);
}
}
class PublicRSAKeyReader {
public static RSAPublicKey getKeyFile(String filename) throws Exception {
File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int) f.length()];
dis.readFully(keyBytes);
dis.close();
return PublicRSAKeyReader.generateKey(keyBytes);
}
public static RSAPublicKey getKey(String base64) throws Exception {
byte[] keyBytes = Base64.decode(base64);
return PublicRSAKeyReader.generateKey(keyBytes);
}
private static RSAPublicKey generateKey(byte[] keyBytes) throws Exception {
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
return (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(spec);
}
}
이 코드 조각은 다음 트릭을 수행해야합니다.
,210
String signedMessage = ""; // load Base64 coded the message generated in Java here.
byte[] message = Convert.FromBase64String(signedMessage);
String messageString = Encoding.ASCII.GetString(message);
String[] lines = Regex.Split(messageString, "\n");
byte[] content = Convert.FromBase64String(lines[0]); // first line of the message were the content
byte[] signature = Convert.FromBase64String(lines[1]); // second line were the signature
RSACryptoServiceProvider rsaObj = new RSACryptoServiceProvider(2048);
//Create a new instance of the RSAParameters structure.
RSAParameters rsaPars = new RSAParameters();
rsaPars.Modulus = Convert.FromBase64String("insert your modulus revealed in the Java example here");
rsaPars.Exponent = Convert.FromBase64String("AQAB"); // Exponent. Should always be this.
// Import key parameters into RSA.
rsaObj.ImportParameters(rsaPars);
// verify the message
Console.WriteLine(rsaObj.VerifyData(Encoding.ASCII.GetBytes(lines[0]), "SHA1", signature));
코드는 사용 :
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
내가 자유롭게 Base64로 다른 계층에 최종 메시지를 포장하는 것은 조금 잔인한 변경 될 것을 인정한다.
시도하고있는 'C#'코드를 보여주십시오. – ja72
철저한 googeling에, 나는 메시지를 암호문을 해독하기 위하여 공개 RSA 열쇠를 사용하여 MS가 당신을시키는 것을 제외하고 2 개의 결점이,다는 것을 부탁에왔다. RSA는 modulus/key와 같은 크기의 경합 만 처리 할 수 있습니다. 2048의 경우이 제한은 245 자입니다. –
개인 키로 암호화 할 때는 실제로 서명해야합니다. 어쨌든 누구나 잠재적으로 콘텐츠를 읽을 수 있으므로 서명을 사용하여 콘텐츠가 1인지 확인해야합니다. 개인 키의 소유자로부터 오는 것입니다. , 2)는 수정되지 않았습니다. –