Eccoci al terzo e ultimo episodio della saga sulla sicurezza della vostra password del database. In due post precedenti abbiamo visto come e . Se però non lavorate né con JBoss né con Tomcat, usate Spring e preferite far gestire il datasource a lui e rimanere più generici possibili, ecco come criptare la password con il semplice aiuto di un framework esterno, ovvero Jasypt!
Encryption for dummies
Il problema della sicurezza e degli algoritmi di criptaggio è un mondo che conosco poco, ma se quello che ti interessa è avere un certo livello di sicurezza nella cifratura della tua password senza sbatterti troppo, questo è il framework che fa per te! (E per me!) Soprattutto perché nativamente si integra con Spring. Per includerlo nel vostro progetto basta inserire nel pom:
org.jasypt jasypt-spring31 1.9.2
Partiamo però dall’inizio.
C’era una volta un datasource…
Nei progetti Spring che gestiscono il datasource (invece che chiederlo in JNDI al server), la sua dichiarazione è qualcosa del tipo:
dove i parametri vengono letti da un semplice file di properties (chiave/valore) con:
db.username=test db.password=test db.driver=com.mysql.jdbc.Driver db.url=jdbc:mysql://localhost:3306/test db.dialect=org.hibernate.dialect.MySQL5Dialect db.initialSize=10 db.maxActive=50
Fin qui niente di nuovo. Occhio alla classe del datasource: come suggerisce il javadoc di Spring, è buona norma usare un connection pool e non il datasource fornito da Spring stesso in un ambiente di produzione.
Jasypt in azione!
Jasypt mette a disposizione un namespace specifico per Spring in modo da configurare l’algoritmo di cifratura che useremo e su quali file di properties verrà applicato. Per chi lo preferisce, può usare la dichiarazione esplicita dei bean coinvolti nella configurazione e mascherati dai tag di Jasypt.
Ci basta quindi sostituire util:properties con:
- encryptor-config: dichiara un bean encryptor di configurazione dove scelgo l’algoritmo di cifratura e una parola chiave usata nella codifica (lo stesso che abbiamo usato nel post dedicato a Tomcat).
- string-encryptor: applica la configurazione ad un encryptor di stringhe;
-
encryptable-property-placeholder: carica il file di properties e tenta di decifrare le voci criptate. Come fa a riconoscerle? Le voci codificate sono dichiarate così:
db.password=ENC(vz8Xp5eOh2jIb8RZi6IDUg==)
Semplice no? Tre righe di xml e la password è protetta! Ma da dove è uscita? Possiamo calcolarcela in modo piuttosto semplice.
Creiamo la nostra password cifrata
Purtroppo, a differenza di come abbiamo visto con JBoss, dobbiamo farci un nostro main per criptare la password da sostituire nel file di properties.
Per essere sicuri di usare lo stesso encryptor che Jasypt userà per la decodifica, creiamo un semplice bean e glielo iniettiamo:
Scriviamo quindi un semplice main che carica il contesto Spring e codifica la password passata come argomento:
public class EncryptionUtils { private StandardPBEStringEncryptor encryptor; public String encrypt(String plain) { return encryptor.encrypt(plain); } public static void main(String[] args) { try (ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "classpath:db.xml");) { EncryptionUtils encryptionUtils = context.getBean(EncryptionUtils.class); System.out.println(encryptionUtils.encrypt(args[0])); } } public void setEncryptor(StandardPBEStringEncryptor encryptor) { this.encryptor = encryptor; } }
Abbiamo quindi pronta la password da sostituire nel nostro file di properties!! Questo esempio è stato testato con Spring >= 3.1. Per le versioni precedenti dal sito di Jasypt è possibile trovare le soluzioni più adatte alla vostra versione.
Un piccolo approfondimento
Come nel post dedicato alla cifratura della password per JBoss, anche in questo caso non abbiamo fatto altro che spostare il problema. Riprendiamo la configurazione dell’algoritmo:
Per un utente esperto, conoscere l’algoritmo e la sua password di cifratura, è un attimo risalire alla password del database. Fortunatamente Jasypt offre altri due modi per passare la password di cifratura. Possiamo infatti sostituire l’attributo password con:
- password-env-name: possiamo far riferimento ad una variabile d’ambiente nella quale registreremo la password. Una volta avviato il sistema può essere tolta senza problemi.
- password-sys-property-name: possiamo passare la password come parametro della JVM, in modo da non averla scritta fisicamente nella configurazione del nostro applicativo.
Lo stesso tipo di sicurezza può essere applicato anche all’attributo algorithm in modo da non essere dichiarato esplicitamente nella configurazione.
Dovendo scegliere, preferirei la prima di queste due soluzioni perché non lascia traccia nel sistema della password dell’algoritmo di cifratura.