Hoi,
Ik ben een Android app aan het schrijven (in Java) waar gebruikers hun wachtwoord voor een bepaald forum moeten invoeren. Mijn app heeft dit wachtwoord nodig om in te loggen op het forum en daar data vanaf te halen.
Het inloggen op het forum en het data ophalen gebeurt echter allemaal in een webservice op mijn webserver (om verscheidene redenen). Om het een en ander veilig te houden bedacht ik dat het mogelijk zou moeten zijn om het wachtwoord in mijn app (Java), die encrypted string op te sturen naar mijn webservice, om hem daar weer te decrypten en het originele wachtwoord te gebruiken. Ik zou dan een symmetrisch algoritme gebruiken (bijvoorbeeld Rijndael en AES kom ik veel tegen), dat in de app en in de webservice dezelfde key gebruikt, die niemand anders mag weten.
Ten eerste: is dit veilig, of vergis ik me nu? Ik denk dat het verzenden van data van een android app (via HTTP POST) onderschept kan worden en het wachtwoord dus gezien zou kunnen worden, niet? Als het wachtwoord encrypted is kan niemand er natuurlijk wat mee, tenzij ze de key weten. En daar ligt nu net een punt waar ik vaak tegenaan loop: kun je een Android app niet gewoon decompilen en zo de key uitlezen? Hoe zit dat met elk ander encryptie algoritme, je moet toch ergens de key opslaan, en waarom kan men die dan niet zomaar uitlezen?
Ik heb voor nu maar even aangenomen dat dit een veilige manier is om met het wachtwoord om te gaan (zo niet, advies om dit te verbeteren is handig!). Maar nu krijg ik het niet voor elkaar om een string in Java te encrypten en in .NET weer te decrypten. Of ik krijg allemaal errors (aan een of beide kanten), of ik krijg na decrypten gewoon iets anders terug.
Ik weet niet heel veel van de theorie dus ik raak nogal gauw verstrengeld in de verschillende implementaties, modes, settings, etc, en die zullen natuurlijk allemaal gelijk moeten zijn aan beide kanten om het originele wachtwoord weer terug te krijgen...
In Java gebruik ik op dit moment deze code om een wachtwoord te encrypten (Key en IV zijn natuurlijk even gauw verzonnen);
Base64Coder is een class die ik op internet gevonden heb, ik neem maar even voor het gemak (bij gebrek aan beter weten) aan dat die de bytes correct naar een base-64 string converteert.
Als ik hier bijvoorbeeld het wachtwoord "test" mee encrypt krijg ik "[C@bb273cc" terug.
Nu probeer ik dit in C# weer te decrypten met deze code, en ontelbaar veel variaties daar op, maar het wil niet lukken:
In dit geval geeft hij "Length of the data to decrypt is invalid." na de CryptoStream.Write call. Ik heb geprobeerd andere encoding te gebruiken (Encoding.Unicode bijv), wat ik soms tegen kom online, maar dan zeurt hij dat de IV niet de goeie lengte heeft. Ik heb geprobeerd RijndaelManaged te gebruiken, zelfde problemen. Ik heb geprobeerd aan de Java kant de string als Hex terug te geven, weer hetzelfde...
Ik ben bang dat ik hier niet verder mee ga komen omdat ik gewoon niet goed weet wat voor settings ik allemaal kan en moet wijzigen, welke encoding ik moet gebruiken, etc.
Kan iemand misschien een tip geven hoe ik dit het beste kan aanpakken? Ik kom online heel veel libraries tegen die allemaal encrypties kunnen toepassen, maar daar heb ik niet zoveel aan als ze niet dezelfde settings en algoritmes gebruiken natuurlijk. Zijn er misschien implementaties die voor Java en C# beide werken?
Bedankt!
Ik ben een Android app aan het schrijven (in Java) waar gebruikers hun wachtwoord voor een bepaald forum moeten invoeren. Mijn app heeft dit wachtwoord nodig om in te loggen op het forum en daar data vanaf te halen.
Het inloggen op het forum en het data ophalen gebeurt echter allemaal in een webservice op mijn webserver (om verscheidene redenen). Om het een en ander veilig te houden bedacht ik dat het mogelijk zou moeten zijn om het wachtwoord in mijn app (Java), die encrypted string op te sturen naar mijn webservice, om hem daar weer te decrypten en het originele wachtwoord te gebruiken. Ik zou dan een symmetrisch algoritme gebruiken (bijvoorbeeld Rijndael en AES kom ik veel tegen), dat in de app en in de webservice dezelfde key gebruikt, die niemand anders mag weten.
Ten eerste: is dit veilig, of vergis ik me nu? Ik denk dat het verzenden van data van een android app (via HTTP POST) onderschept kan worden en het wachtwoord dus gezien zou kunnen worden, niet? Als het wachtwoord encrypted is kan niemand er natuurlijk wat mee, tenzij ze de key weten. En daar ligt nu net een punt waar ik vaak tegenaan loop: kun je een Android app niet gewoon decompilen en zo de key uitlezen? Hoe zit dat met elk ander encryptie algoritme, je moet toch ergens de key opslaan, en waarom kan men die dan niet zomaar uitlezen?
Ik heb voor nu maar even aangenomen dat dit een veilige manier is om met het wachtwoord om te gaan (zo niet, advies om dit te verbeteren is handig!). Maar nu krijg ik het niet voor elkaar om een string in Java te encrypten en in .NET weer te decrypten. Of ik krijg allemaal errors (aan een of beide kanten), of ik krijg na decrypten gewoon iets anders terug.
Ik weet niet heel veel van de theorie dus ik raak nogal gauw verstrengeld in de verschillende implementaties, modes, settings, etc, en die zullen natuurlijk allemaal gelijk moeten zijn aan beide kanten om het originele wachtwoord weer terug te krijgen...
In Java gebruik ik op dit moment deze code om een wachtwoord te encrypten (Key en IV zijn natuurlijk even gauw verzonnen);
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| public class PasswordEncryption { private static final String KEY = "1234567890123456"; private static final String IV = "abcdefghijklmnop"; public static String encryptPassword(String password) throws Exception { SecretKeySpec key = new SecretKeySpec(KEY.getBytes(), "AES"); AlgorithmParameterSpec IVspec = new IvParameterSpec(IV.getBytes()); Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] encryptedBytes = cipher.doFinal(password.getBytes()); return Base64Coder.encode(encryptedBytes).toString(); } } |
Base64Coder is een class die ik op internet gevonden heb, ik neem maar even voor het gemak (bij gebrek aan beter weten) aan dat die de bytes correct naar een base-64 string converteert.
Als ik hier bijvoorbeeld het wachtwoord "test" mee encrypt krijg ik "[C@bb273cc" terug.
Nu probeer ik dit in C# weer te decrypten met deze code, en ontelbaar veel variaties daar op, maar het wil niet lukken:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| public static class PasswordEncryption { private const string KEY = "1234567890123456"; private const string IV = "abcdefghijklmnop"; public static string Decrypt(string encryptedPassword) { using (var aes = new AesManaged()) { aes.Padding = PaddingMode.PKCS7; aes.KeySize = 128; aes.Key = System.Text.Encoding.UTF8.GetBytes(KEY); aes.IV = System.Text.Encoding.UTF8.GetBytes(IV); byte[] cipherText = System.Text.Encoding.UTF8.GetBytes(encryptedPassword); byte[] plainText = null; using (MemoryStream ms = new MemoryStream()) { using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write)) { cs.Write(cipherText, 0, cipherText.Length); } plainText = ms.ToArray(); } string s = System.Text.Encoding.UTF8.GetString(plainText); return s; } } } |
In dit geval geeft hij "Length of the data to decrypt is invalid." na de CryptoStream.Write call. Ik heb geprobeerd andere encoding te gebruiken (Encoding.Unicode bijv), wat ik soms tegen kom online, maar dan zeurt hij dat de IV niet de goeie lengte heeft. Ik heb geprobeerd RijndaelManaged te gebruiken, zelfde problemen. Ik heb geprobeerd aan de Java kant de string als Hex terug te geven, weer hetzelfde...
Ik ben bang dat ik hier niet verder mee ga komen omdat ik gewoon niet goed weet wat voor settings ik allemaal kan en moet wijzigen, welke encoding ik moet gebruiken, etc.
Kan iemand misschien een tip geven hoe ik dit het beste kan aanpakken? Ik kom online heel veel libraries tegen die allemaal encrypties kunnen toepassen, maar daar heb ik niet zoveel aan als ze niet dezelfde settings en algoritmes gebruiken natuurlijk. Zijn er misschien implementaties die voor Java en C# beide werken?
Bedankt!