Sto tentando con scarso successo alla porta sopra il codice di Google per generare un token sicuro per la loro captcha (https://github.com/google/recaptcha-java/blob/master/appengine/src/main/java/com/google/recaptcha/STokenUtils.java):porting Java crittografia di routine per C#
L'utilità originale ha il seguente:
private static final String CIPHER_INSTANCE_NAME = "AES/ECB/PKCS5Padding";
private static String encryptAes(String input, String siteSecret) {
try {
SecretKeySpec secretKey = getKey(siteSecret);
Cipher cipher = Cipher.getInstance(CIPHER_INSTANCE_NAME);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return BaseEncoding.base64Url().omitPadding().encode(cipher.doFinal(input.getBytes("UTF-8")));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static SecretKeySpec getKey(String siteSecret){
try {
byte[] key = siteSecret.getBytes("UTF-8");
key = Arrays.copyOf(MessageDigest.getInstance("SHA").digest(key), 16);
return new SecretKeySpec(key, "AES");
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
public static void main(String [] args) throws Exception {
//Hard coded the following to get a repeatable result
String siteSecret = "12345678";
String jsonToken = "{'session_id':'abf52ca5-9d87-4061-b109-334abb7e637a','ts_ms':1445705791480}";
System.out.println(" json token: " + jsonToken);
System.out.println(" siteSecret: " + siteSecret);
System.out.println(" Encrypted stoken: " + encryptAes(jsonToken, siteSecret));
Dato i valori che ho codificato, ottengo Irez-rWkCEqnsiRLWfol0IXQu1JPs3qL_G_9HfUViMG9u4XhffHqAyju6SRvMhFS86czHX9s1tbzd6B15r1vmY6s5S8odXT-ZE9A-y1lHns"
come mio token crittografato.
Le mie competenze di Java e crittografia sono più che un po 'arrugginite e non ci sono sempre analoghi diretti in C#. Ho cercato di fondere encrypeAes()
e getKey()
con la seguente, che non è corretto:
public static string EncryptText(string PlainText, string siteSecret)
{
using (RijndaelManaged aes = new RijndaelManaged())
{
aes.Mode = CipherMode.ECB;
aes.Padding = PaddingMode.PKCS7;
var bytes = Encoding.UTF8.GetBytes(siteSecret);
SHA1 sha1 = SHA1.Create();
var shaKey = sha1.ComputeHash(bytes);
byte[] targetArray = new byte[16];
Array.Copy(shaKey, targetArray, 16);
aes.Key = targetArray;
ICryptoTransform encrypto = aes.CreateEncryptor();
byte[] plainTextByte = ASCIIEncoding.UTF8.GetBytes(PlainText);
byte[] CipherText = encrypto.TransformFinalBlock(plainTextByte, 0, plainTextByte.Length);
return HttpServerUtility.UrlTokenEncode(CipherText); //Equivalent to java's BaseEncoding.base64Url()?
}
}
La versione C# produce il valore errato di: Ye+fySvneVUZJXth67+Si/e8fBUV4Sxs7wEXVDEOJjBMHl1encvt65gGIj8CiFzBGp5uUgKYJZCuQ4rc964vZigjlrJ/430LgYcathLLd9U=
SHA1 Implementato hashing, ancora nessuna gioia. –
Si potrebbe provare a usare ['AesManaged'] (https://msdn.microsoft.com/en-us/library/system.security.cryptography.aesmanaged%28v=vs.100%29.aspx) invece di' RijndaelManaged' (che ha diverse dimensioni della chiave di default e quindi non è lo * standard * AES) per abbinare la parte Java 'CIPHER_INSTANCE_NAME =" AES/ECB/PKCS5Padding "' e usare ['Convert.ToBase64String'] (https: // msdn.microsoft.com/en-us/library/dhx0d524%28v=vs.110%29.aspx) invece di 'HttpServerUtility.UrlTokenEncode ...'. – pasty
Aggiornato per includere l'output C#. @pasty ho aggiornato a 'AESManaged', ma non sono chiaro su come vorrei allineare con il nome del codice. Ho optato per 'PaddingMode.PKCS7' per http://blog.zebsadiq.com/post/AESCBCPKCS5Padding-EncryptionDecryption-in-C.aspx, ma ammetto che sto armeggiando. Il passaggio a 'Convert.ToBase64String' non ha avuto alcun effetto sul risultato. Ho optato per 'HttpServerUtility.UrlTokenEncode' come sembrava più vicino a BaseEncoding.base64Url() di Java. –