2011-02-03 17 views
1

これは既存の質問がたくさんあるトピックですが、私は正確なケースをカバーする既存の回答を見つけることができません。JavaでC#で生成されたDSA署名を確認する

いくつかのJavaコードで文字列(URL)に署名し、その文字列をC#プログラムに渡す必要があります。

私は、DSA鍵ペアを生成するために、一度、次のJavaコードを実行します。

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", "SUN"); 
SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN"); 
keyGen.initialize(1024, random); 

KeyPair pair = keyGen.generateKeyPair(); 
PrivateKey priv = pair.getPrivate(); 
PublicKey pub = pair.getPublic(); 

/* save the private key in a file */ 
byte[] privkey = priv.getEncoded(); 
FileOutputStream privkeyfos = new FileOutputStream("key.priv"); 
privkeyfos.write(privkey); 
privkeyfos.close(); 

/* save the public key in a file */ 
byte[] pubkey = pub.getEncoded(); 
FileOutputStream pubkeyfos = new FileOutputStream("key.public"); 
pubkeyfos.write(pubkey); 
pubkeyfos.close(); 

私は、署名を生成するには、次のコードを使用しています。私のC#のコードで

public static String Sign(String keyPath, byte[] data) 
{ 
    FileInputStream keyfis = new FileInputStream(new File(keyPath, "key.priv")); 
    byte[] encKey = new byte[keyfis.available()]; 
    keyfis.read(encKey); 
    keyfis.close(); 

    PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(encKey); 
    KeyFactory keyFactory = KeyFactory.getInstance("DSA"); 
    PrivateKey privKey = keyFactory.generatePrivate(privKeySpec); 

    Signature dsa = Signature.getInstance("SHA1withDSA", "SUN"); 

    dsa.initSign(privKey); 

    ByteArrayInputStream in = new ByteArrayInputStream(data); 
    BufferedInputStream bufin = new BufferedInputStream(in); 
    byte[] buffer = new byte[1024]; 
    int len; 
    while ((len = bufin.read(buffer)) >= 0) 
    { 
    dsa.update(buffer, 0, len); 
    } 
    bufin.close(); 

    byte[] realSig = dsa.sign(); 

    return new String(Base64.encodeBase64(realSig), "UTF-8"); 
} 

は、私は、文字列、Base64でエンコードされた署名と最初のステップからの「key.public」ファイルへのアクセス権を持っています。

文字列が改ざんされているかどうかを判断するために、これらの要素と適切なライブラリを組み合わせたコードブロックを提供できますか?

+0

グーグル「C#dsa verify example」はヒット数が多く、これらの例があなたのニーズをどのように満たしていないのか説明できますか? –

+0

[C#でのDSA署名の検証]の複製が可能です。(http://stackoverflow.com/questions/1628305/verify-dsa-signature-in-c) –

+0

@GregSリンク先の質問は私の質問に答える最良の候補者でした私が持っている "key.private"ファイルをどのように読み込むかについての詳細は含まれていません。 – mchr

答えて

1

私は今、いくつかのキー入力がこの記事から来るでこれを解決した:http://www.codeproject.com/KB/security/CryptoInteropSign.aspx

主な検証は、次のC#の機能を使用して行われます。

private static Boolean isValid(String xiString, String xiSig) 
{ 
    AsnKeyParser keyParser = new AsnKeyParser("path/to/key.public"); 
    DSAParameters publicKey = keyParser.ParseDSAPublicKey(); 

    DSACryptoServiceProvider DSA = new DSACryptoServiceProvider(); 
    DSA.ImportParameters(publicKey); 
    DSASignatureDeformatter DSADeformatter = new DSASignatureDeformatter(DSA); 
    UTF8Encoding UTF8 = new UTF8Encoding(); 
    byte[] plainBytes = UTF8.GetBytes(xiString);  
    var sha1 = new SHA1Managed(); 
    var hash = sha1.ComputeHash(plainBytes); 
    byte[] asn1SigBytes = Convert.FromBase64String(xiSig); 
    byte[] sigBytes = ConvertToP1363Signature(asn1SigBytes); 
    Boolean retVal = DSADeformatter.VerifySignature(hash, sigBytes); 
    return retVal; 
} 

これは2つのヘルパーメソッドに依存します。

1)AsnKeyParserはリンクされた記事に添付されたクラスです。この記事では、AsnKeyParser.csとBerDecodeError.csという2つのファイルを使用したC#ダウンロードを提供しています。 AsnKeyParserからRSA関数を削除し、BigIntegerファイルの依存関係を削除しました。

このクラスは、Javaコードで作成された「key.public」ファイルの解析を処理します。

2)Javaによって生成された46-48バイトのDERで符号化された署名を、C#が受け入れるDSA署名に変換する機能。

この機能は、リンクされた記事のコメントのコードに基づいています。

private static byte[] ConvertToP1363Signature(byte[] ASN1Sig) 
{ 
    AsnParser asn = new AsnParser(ASN1Sig); 
    asn.NextSequence(); 
    byte[] r = asn.NextInteger(); 
    byte[] s = asn.NextInteger(); 

    // Returned to caller 
    byte[] p1363Signature = new byte[40]; 

    if (r.Length > 21 || (r.Length == 21 && r[0] != 0)) 
    { 
    // WTF??? 
    // Reject - signature verification failed 
    } 
    else if (r.Length == 21) 
    { 
    // r[0] = 0 
    // r[1]'s high bit *should* be set 
    Array.Copy(r, 1, p1363Signature, 0, 20); 
    } 
    else if (r.Length == 20) 
    { 
    // r[0]'s high bit *should not* be set 
    Array.Copy(r, 0, p1363Signature, 0, 20); 
    } 
    else 
    { 
    // fewer than 20 bytes 
    int len = r.Length; 
    int off = 20 - len; 
    Array.Copy(r, 0, p1363Signature, off, len); 
    } 

    if (s.Length > 21 || (s.Length == 21 && s[0] != 0)) 
    { 
    // WTF??? 
    // Reject - signature verification failed 
    } 
    else if (s.Length == 21) 
    { 
    // s[0] = 0 
    // s[1]'s high bit *should* be set 
    Array.Copy(s, 1, p1363Signature, 20, 20); 
    } 
    else if (s.Length == 20) 
    { 
    // s[0]'s high bit *should not* be set 
    Array.Copy(s, 0, p1363Signature, 20, 20); 
    } 
    else 
    { 
    // fewer than 20 bytes 
    int len = s.Length; 
    int off = 40 - len; 
    Array.Copy(s, 0, p1363Signature, off, len); 
    } 

    return p1363Signature; 
} 
+0

(このコメントを削除しようとしましたが失敗しました) – SonarJetLens

関連する問題