1
1
package shop .algebras
2
2
3
- import javax .crypto .spec .{ PBEKeySpec , SecretKeySpec }
3
+ import java .security .SecureRandom
4
+ import java .util .Base64
5
+ import javax .crypto .spec .{IvParameterSpec , PBEKeySpec , SecretKeySpec }
4
6
import javax .crypto .{ Cipher , SecretKeyFactory }
5
7
6
8
import shop .config .data .PasswordSalt
7
9
import shop .domain .auth ._
8
10
9
11
import cats .effect .Sync
10
12
import cats .syntax .all ._
13
+ import eu .timepit .refined .auto ._
11
14
12
15
trait Crypto {
13
16
def encrypt (value : Password ): EncryptedPassword
@@ -18,15 +21,19 @@ object LiveCrypto {
18
21
def make [F [_]: Sync ](secret : PasswordSalt ): F [Crypto ] =
19
22
Sync [F ]
20
23
.delay {
21
- val salt = secret.value.value.value.getBytes(" UTF-8" )
24
+ val random = new SecureRandom ()
25
+ val ivBytes = new Array [Byte ](16 )
26
+ random.nextBytes(ivBytes)
27
+ val iv = new IvParameterSpec (ivBytes);
28
+ val salt = secret.value.value.getBytes(" UTF-8" )
22
29
val keySpec = new PBEKeySpec (" password" .toCharArray(), salt, 65536 , 256 )
23
30
val factory = SecretKeyFactory .getInstance(" PBKDF2WithHmacSHA1" )
24
31
val bytes = factory.generateSecret(keySpec).getEncoded
25
32
val sKeySpec = new SecretKeySpec (bytes, " AES" )
26
- val eCipher = EncryptCipher (Cipher .getInstance(" AES" ))
27
- eCipher.value.init(Cipher .ENCRYPT_MODE , sKeySpec)
28
- val dCipher = DecryptCipher (Cipher .getInstance(" AES" ))
29
- dCipher.value.init(Cipher .DECRYPT_MODE , sKeySpec)
33
+ val eCipher = EncryptCipher (Cipher .getInstance(" AES/CBC/PKCS5Padding " ))
34
+ eCipher.value.init(Cipher .ENCRYPT_MODE , sKeySpec, iv )
35
+ val dCipher = DecryptCipher (Cipher .getInstance(" AES/CBC/PKCS5Padding " ))
36
+ dCipher.value.init(Cipher .DECRYPT_MODE , sKeySpec, iv )
30
37
(eCipher, dCipher)
31
38
}
32
39
.map {
@@ -40,21 +47,18 @@ final class LiveCrypto private (
40
47
dCipher : DecryptCipher
41
48
) extends Crypto {
42
49
43
- // Workaround for PostgreSQL ERROR: invalid byte sequence for encoding "UTF8": 0x00
44
- private val Key = " =DownInAHole="
45
-
46
50
def encrypt (password : Password ): EncryptedPassword = {
47
- val bytes = password.value.getBytes( " UTF-8 " )
48
- val result = new String (eCipher .value.doFinal(bytes), " UTF-8" )
49
- val removeNull = result.replaceAll( " \\ u0000 " , Key )
50
- EncryptedPassword (removeNull )
51
+ val base64 = Base64 .getEncoder( )
52
+ val bytes = password .value.getBytes( " UTF-8" )
53
+ val result = new String (base64.encode(eCipher.value.doFinal(bytes)), " UTF-8 " )
54
+ EncryptedPassword (result )
51
55
}
52
56
53
57
def decrypt (password : EncryptedPassword ): Password = {
54
- val bytes = password.value.getBytes( " UTF-8 " )
55
- val result = new String (dCipher .value.doFinal(bytes), " UTF-8" )
56
- val insertNull = result.replaceAll( Key , " \\ u0000 " )
57
- Password (insertNull )
58
+ val base64 = Base64 .getDecoder( )
59
+ val bytes = base64.decode(password .value.getBytes( " UTF-8" ) )
60
+ val result = new String (dCipher.value.doFinal(bytes) , " UTF-8 " )
61
+ Password (result )
58
62
}
59
63
60
64
}
0 commit comments