最近在寫一個Java的訊息伺服器,同時需要做一個.NET版本的客戶端。他們之間需要安全通訊,基於一些簡單的密碼協議,用到公鑰加密、對稱加密、Hash演算法。這個過程中,我對這兩個平台的加密部分有了一定了解,以下也是我的一些新的認識吧。
1.對稱加密
1) Java 1.5的對稱加密很簡單,提供的演算法也較多。可以說是,使用簡單,傻瓜式,而且功能齊全。
例如:
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decryptText = cipher.doFinal(data);
2) .NET 2.0的對稱加密,缺省加密模式是CBC,CBC加密的時候,需要一個密鑰的同時,還需要初始化向量IV,這會使得初學入者使用起來不方便,這個問題到是十分容易對付的,修改一下配置就好了。
SymmetricAlgorithm algorithm = SymmetricAlgorithm.Create(algorithmName);
algorithm.Mode = CipherMode.ECB;
algorithm.Key = key;
algorithm.Padding = PaddingMode.PKCS7;透過這種設定之後,就能夠跟Java通訊操作,互為加密解密。
3) .NET 2.0和Java 1.5方面,加密演算法的名字有些地方稍有差異。
AES <==> Rijndael
DESede <==> TripleDES
這是似乎是常識。
2.公鑰加密演算法RSA
1) Java 1.5中,RSAPublicKey進行getEncoded()得到位元組數組是ASN.1編碼的。逆轉回來需要使用X509EncodedKeySpec,這個細節需要閱讀文件細節或是對密碼學有一定了解才知道。例如:
//public key ==> bytes
PublicKey publicKey =
byte[] rawPublicKey = publicKey.getEncoded();
// bytes ==> public key
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(rawPublicKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key newPublicKey = keyFactory.generatePublic(x509KeySpec);
除此之外,Java的公鑰加密部分,還是相當容易使用的。風格依然是功能簡單,傻瓜式使用,功能齊全。
Java中,支援ASN.1編碼,但隱藏其中,使用者完全覺察不到。
2) .NET 2.0中,設計有些混亂,不支援ASN.1編碼。但是Mono似乎在做ASN.1編碼的支援。為此我自己借鏡一個Java開元JCE的實現,實作了一個.NET版本的ASN Parser和ASN Builder,花了兩天時間。如下:
public static RSAParameters ASN1ToPublicKey(byte[] rawPublicKey)
{
ASN1InputStream asnInput = new ASN1InputStream(rawPublicKey);
ASN1Sequence asnSeq = (ASN1Sequence)asnInput.ReadObject();
SubjectPublicKeyInfo subjectPublicKeyInfo = new SubjectPublicKeyInfo(asnSeq);
DERObjectIdentifier algOid = subjectPublicKeyInfo.AlgorithmId.ObjectId;
RSAPublicKeyStructure pubKey = new RSAPublicKeyStructure(
(ASN1Sequence)subjectPublicKeyInfo.PublicKey);
byte[] modulus = pubKey.Modulus;
byte[] publicExponent = pubKey.PublicExponent;
RSAParameters pram = new RSAParameters();
pram.Modulus = modulus;
pram.Exponent = publicExponent;
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(pram);
return pram;
}
public static byte[] PublicKeyToASN1(RSAParameters pram)
{
SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption,
new DERNull()), new RSAPublicKeyStructure(pram.Modulus, pram.Exponent).DERObject);
byte[] rawPublicKey = info.GetDEREncoded();
return rawPublicKey;
}
3、總體感覺
1) Java的安全模組設計得還是很好的,簡單好用,功能也齊全。
2) .NET 2.0則有點亂,命名風格和系統框架有些不協調,功能欠缺,程式碼組織的不夠理想。
3) 在Mono中,對安全的支援要比微軟已發布的要好,從網上可以看到,.NET Framework 2.0的一些特性也是從Mono中藉鑑過來的。
4) 甚至可以認為,.NET加密模組的開發團隊能力可能不是很強。就如那一句話「寫出糟糕的程式碼並非我們的專利」。
http://www.cnblogs.com/jobs/archive/2006/09/22/512297.html