Jasypt Users Forum

Performance of StandardPBEByteEncryptor using Spring

View: New views
6 Messages — Rating Filter:   Alert me  

Performance of StandardPBEByteEncryptor using Spring

by Mike Rowehl :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hey folks, I tried searching for this, but haven't found anything yet (sorry if it's there and I'm just looking for the wrong stuff).  I have a project that's using the Hibernate initialization using Spring to provide the encryptor, as described here:

http://jasypt.org/hibernate3.html

The code is working, encryption and decryption performed, peachy.  However, when I have the system running within Tomcat I see very slow response times when there are multiple requests hitting encrypted columns.  If I do a thread dump when things are performing poorly I see a number of threads all waiting for the same decryptor object.  Thead dump excerpt:

"http-5801-25" daemon prio=10 tid=0x0000000045ba2400 nid=0x2abd waiting for monitor entry [0x00000000461dd000..0x00000000461dfb10]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at org.jasypt.encryption.pbe.StandardPBEByteEncryptor.decrypt(StandardPBEByteEncryptor.java:784)
        - waiting to lock <0x00002aaab33e0270> (a javax.crypto.Cipher)
        at org.jasypt.encryption.pbe.StandardPBEStringEncryptor.decrypt(StandardPBEStringEncryptor.java:639)
        at org.jasypt.hibernate.type.AbstractEncryptedAsStringType.nullSafeGet(AbstractEncryptedAsStringType.java:143)
        at org.hibernate.type.CustomType.nullSafeGet(CustomType.java:105)
        at org.hibernate.type.AbstractType.hydrate(AbstractType.java:81)
        at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2096)
        at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1380)
        at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1308)

Many of the threads are waiting on exactly the same object it looks like.  I'm an admitted Spring/Hibernate/Tomcat noob, but I'm assuming what's happening is that the encryptor being used by Hibernate is a singleton cause of the way Spring initializes it, and all the Tomcat threads are all jammed up waiting for the same object.

Am I misinterpreting what's going on, or does this seem likely?  And if so, is there a different way to configure these objects so that I can avoid contention on a shared resource?  Thanks,

- Mike

Re: Performance of StandardPBEByteEncryptor using Spring

by dfernandez :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

+------------------------+
  Jasypt Users List      
  http://www.jasypt.org 
+------------------------+

Hello Mike,

Yes and no :-). It is true that Spring will treat your bean as as
singleton by default, unless you set a "prototype" scope to it... but
the fact is that jasypt's own hibernate encryption type uses the
encryptor as a singleton, always.... not exactly a singleton, but a
hibernate-type-instance-wide singleton.

If I understood correctly, you are using the same encryptor to encrypt
more than one database column. If this is the case, I can give you a
workaround:

  1st: If you only defined your StandardPBEStringEncryptor as a Spring
bean with the aim of passing it to the hibernate container
(HibernatePBEStringEncryptor), declare your encryptor as
"scope="prototype"". This way Spring will return a new instance of the
encryptor (with the same configuration) to each other object that asks
for it. (If you didn't define it only for this, maybe it's safer to
define a new prototye bean, with the same configuration as the original
one).

  2nd: Define several "HibernatePBEStringEncryptor" beans, one for each
of your encrypted columns, and pass your StandardPBEStringEncryptor to
all of them, but setting a different "registeredName" for each. As you
defined your StandardPBEStringEncryptor as prototype, Spring will
provide a different instance of it to each of your
"HibernatePBEStringEncryptor"'s, and this way you will have several
instances of the encryptor with the same configuration, registered to be
used from hibernate under different names.

  3rd: Define a different hibernate type (a typedef at the mapping file)
for each of your encrypted columns. Each of this typedefs will make use
of a different encryptor by setting a different
"encryptorRegisteredName". One typedef = one
HibernatePBEStringEncryptor. But all the encryptors being used will have
exactly the same configuration, and thus will be perfectly compatible
among them.

  4th: Set a different type (typedef) for each of your encrypted
columns. This way, you will still have singletons... but at least just
one for each column. Performance should improve.


Anyway, this is just a workaround and this solution could be better...
you have made me thought about this issue, and I will probably try to
add some kind of "encryptor pooling" to the next version of jasypt to
avoid encryptors being a bottleneck.


Regards,
Daniel.



Mike Rowehl wrote:

> +------------------------+
>   Jasypt Users List      
>   http://www.jasypt.org 
> +------------------------+
>
> Hey folks, I tried searching for this, but haven't found anything yet (sorry
> if it's there and I'm just looking for the wrong stuff).  I have a project
> that's using the Hibernate initialization using Spring to provide the
> encryptor, as described here:
>
> http://jasypt.org/hibernate3.html
>
> The code is working, encryption and decryption performed, peachy.  However,
> when I have the system running within Tomcat I see very slow response times
> when there are multiple requests hitting encrypted columns.  If I do a
> thread dump when things are performing poorly I see a number of threads all
> waiting for the same decryptor object.  Thead dump excerpt:
>
> "http-5801-25" daemon prio=10 tid=0x0000000045ba2400 nid=0x2abd waiting for
> monitor entry [0x00000000461dd000..0x00000000461dfb10]
>    java.lang.Thread.State: BLOCKED (on object monitor)
> at
> org.jasypt.encryption.pbe.StandardPBEByteEncryptor.decrypt(StandardPBEByteEncryptor.java:784)
> - waiting to lock <0x00002aaab33e0270> (a javax.crypto.Cipher)
> at
> org.jasypt.encryption.pbe.StandardPBEStringEncryptor.decrypt(StandardPBEStringEncryptor.java:639)
> at
> org.jasypt.hibernate.type.AbstractEncryptedAsStringType.nullSafeGet(AbstractEncryptedAsStringType.java:143)
> at org.hibernate.type.CustomType.nullSafeGet(CustomType.java:105)
> at org.hibernate.type.AbstractType.hydrate(AbstractType.java:81)
> at
> org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2096)
> at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1380)
> at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1308)
>
> Many of the threads are waiting on exactly the same object it looks like.
> I'm an admitted Spring/Hibernate/Tomcat noob, but I'm assuming what's
> happening is that the encryptor being used by Hibernate is a singleton cause
> of the way Spring initializes it, and all the Tomcat threads are all jammed
> up waiting for the same object.
>
> Am I misinterpreting what's going on, or does this seem likely?  And if so,
> is there a different way to configure these objects so that I can avoid
> contention on a shared resource?  Thanks,
>
> - Mike
>  


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
jasypt-users mailing list
jasypt-users@...
https://lists.sourceforge.net/lists/listinfo/jasypt-users

Re: Performance of StandardPBEByteEncryptor using Spring

by Mike Rowehl :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Thanks for the reply!  I had considered what you suggest about different beans for the different columns, but in our particular application the contention mostly hits one very high traffic table.  I tested it out and it improved things, but not by enough.

In the meantime I've hacked up an alternative version that:

- uses thread local storage for the encryptor and decryptor member variables
- separates the initialize() method into a one time initializer and thread specific init that instantiates the thread local encryptor and decryptor objects
- and then I removed the syncronize completely from the encryptor/decryptor access cause each thread has it's own

I haven't tested it out too extensively yet, but it seems like it should also be a clean solution (at least for cases where a high degree of concurrency is required).  Happy to share out the version I'm trying if you're interested in it.

- Mike

dfernandez wrote:
+------------------------+
  Jasypt Users List      
  http://www.jasypt.org 
+------------------------+

Hello Mike,

Yes and no :-). It is true that Spring will treat your bean as as
singleton by default, unless you set a "prototype" scope to it... but
the fact is that jasypt's own hibernate encryption type uses the
encryptor as a singleton, always.... not exactly a singleton, but a
hibernate-type-instance-wide singleton.

If I understood correctly, you are using the same encryptor to encrypt
more than one database column. If this is the case, I can give you a
workaround:

  1st: If you only defined your StandardPBEStringEncryptor as a Spring
bean with the aim of passing it to the hibernate container
(HibernatePBEStringEncryptor), declare your encryptor as
"scope="prototype"". This way Spring will return a new instance of the
encryptor (with the same configuration) to each other object that asks
for it. (If you didn't define it only for this, maybe it's safer to
define a new prototye bean, with the same configuration as the original
one).

  2nd: Define several "HibernatePBEStringEncryptor" beans, one for each
of your encrypted columns, and pass your StandardPBEStringEncryptor to
all of them, but setting a different "registeredName" for each. As you
defined your StandardPBEStringEncryptor as prototype, Spring will
provide a different instance of it to each of your
"HibernatePBEStringEncryptor"'s, and this way you will have several
instances of the encryptor with the same configuration, registered to be
used from hibernate under different names.

  3rd: Define a different hibernate type (a typedef at the mapping file)
for each of your encrypted columns. Each of this typedefs will make use
of a different encryptor by setting a different
"encryptorRegisteredName". One typedef = one
HibernatePBEStringEncryptor. But all the encryptors being used will have
exactly the same configuration, and thus will be perfectly compatible
among them.

  4th: Set a different type (typedef) for each of your encrypted
columns. This way, you will still have singletons... but at least just
one for each column. Performance should improve.


Anyway, this is just a workaround and this solution could be better...
you have made me thought about this issue, and I will probably try to
add some kind of "encryptor pooling" to the next version of jasypt to
avoid encryptors being a bottleneck.


Regards,
Daniel.



Mike Rowehl wrote:
> +------------------------+
>   Jasypt Users List      
>   http://www.jasypt.org 
> +------------------------+
>
> Hey folks, I tried searching for this, but haven't found anything yet (sorry
> if it's there and I'm just looking for the wrong stuff).  I have a project
> that's using the Hibernate initialization using Spring to provide the
> encryptor, as described here:
>
> http://jasypt.org/hibernate3.html
>
> The code is working, encryption and decryption performed, peachy.  However,
> when I have the system running within Tomcat I see very slow response times
> when there are multiple requests hitting encrypted columns.  If I do a
> thread dump when things are performing poorly I see a number of threads all
> waiting for the same decryptor object.  Thead dump excerpt:
>
> "http-5801-25" daemon prio=10 tid=0x0000000045ba2400 nid=0x2abd waiting for
> monitor entry [0x00000000461dd000..0x00000000461dfb10]
>    java.lang.Thread.State: BLOCKED (on object monitor)
> at
> org.jasypt.encryption.pbe.StandardPBEByteEncryptor.decrypt(StandardPBEByteEncryptor.java:784)
> - waiting to lock <0x00002aaab33e0270> (a javax.crypto.Cipher)
> at
> org.jasypt.encryption.pbe.StandardPBEStringEncryptor.decrypt(StandardPBEStringEncryptor.java:639)
> at
> org.jasypt.hibernate.type.AbstractEncryptedAsStringType.nullSafeGet(AbstractEncryptedAsStringType.java:143)
> at org.hibernate.type.CustomType.nullSafeGet(CustomType.java:105)
> at org.hibernate.type.AbstractType.hydrate(AbstractType.java:81)
> at
> org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2096)
> at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1380)
> at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1308)
>
> Many of the threads are waiting on exactly the same object it looks like.
> I'm an admitted Spring/Hibernate/Tomcat noob, but I'm assuming what's
> happening is that the encryptor being used by Hibernate is a singleton cause
> of the way Spring initializes it, and all the Tomcat threads are all jammed
> up waiting for the same object.
>
> Am I misinterpreting what's going on, or does this seem likely?  And if so,
> is there a different way to configure these objects so that I can avoid
> contention on a shared resource?  Thanks,
>
> - Mike
>  


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
jasypt-users mailing list
jasypt-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jasypt-users

Re: Performance of StandardPBEByteEncryptor using Spring

by dfernandez :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

+------------------------+
  Jasypt Users List      
  http://www.jasypt.org 
+------------------------+


Hello Mike,

Yours certainly looks like a nice solution, well thought. And thanks for explaining it.

Nevertheless, I will better go for a more generalist pool-based solution in jasypt 1.6, as thread-local solutions can be very adequate for web applications because of its one request - one thread nature, but a little bit trickier at non-web applications where the use of threads is quite more "free"...

Regards,
Daniel.


Mike Rowehl wrote:
+------------------------+
  Jasypt Users List      
  http://www.jasypt.org  
+------------------------+

Thanks for the reply!  I had considered what you suggest about different
beans for the different columns, but in our particular application the
contention mostly hits one very high traffic table.  I tested it out and it
improved things, but not by enough.

In the meantime I've hacked up an alternative version that:

- uses thread local storage for the encryptor and decryptor member variables
- separates the initialize() method into a one time initializer and thread
specific init that instantiates the thread local encryptor and decryptor
objects
- and then I removed the syncronize completely from the encryptor/decryptor
access cause each thread has it's own

I haven't tested it out too extensively yet, but it seems like it should
also be a clean solution (at least for cases where a high degree of
concurrency is required).  Happy to share out the version I'm trying if
you're interested in it.

- Mike


dfernandez wrote:
  
+------------------------+
  Jasypt Users List      
  http://www.jasypt.org  
+------------------------+

Hello Mike,

Yes and no :-). It is true that Spring will treat your bean as as 
singleton by default, unless you set a "prototype" scope to it... but 
the fact is that jasypt's own hibernate encryption type uses the 
encryptor as a singleton, always.... not exactly a singleton, but a 
hibernate-type-instance-wide singleton.

If I understood correctly, you are using the same encryptor to encrypt 
more than one database column. If this is the case, I can give you a 
workaround:

  1st: If you only defined your StandardPBEStringEncryptor as a Spring 
bean with the aim of passing it to the hibernate container 
(HibernatePBEStringEncryptor), declare your encryptor as 
"scope="prototype"". This way Spring will return a new instance of the 
encryptor (with the same configuration) to each other object that asks 
for it. (If you didn't define it only for this, maybe it's safer to 
define a new prototye bean, with the same configuration as the original 
one).

  2nd: Define several "HibernatePBEStringEncryptor" beans, one for each 
of your encrypted columns, and pass your StandardPBEStringEncryptor to 
all of them, but setting a different "registeredName" for each. As you 
defined your StandardPBEStringEncryptor as prototype, Spring will 
provide a different instance of it to each of your 
"HibernatePBEStringEncryptor"'s, and this way you will have several 
instances of the encryptor with the same configuration, registered to be 
used from hibernate under different names.

  3rd: Define a different hibernate type (a typedef at the mapping file) 
for each of your encrypted columns. Each of this typedefs will make use 
of a different encryptor by setting a different 
"encryptorRegisteredName". One typedef = one 
HibernatePBEStringEncryptor. But all the encryptors being used will have 
exactly the same configuration, and thus will be perfectly compatible 
among them.

  4th: Set a different type (typedef) for each of your encrypted 
columns. This way, you will still have singletons... but at least just 
one for each column. Performance should improve.


Anyway, this is just a workaround and this solution could be better... 
you have made me thought about this issue, and I will probably try to 
add some kind of "encryptor pooling" to the next version of jasypt to 
avoid encryptors being a bottleneck.


Regards,
Daniel.



Mike Rowehl wrote:
    
+------------------------+
  Jasypt Users List      
  http://www.jasypt.org  
+------------------------+

Hey folks, I tried searching for this, but haven't found anything yet
(sorry
if it's there and I'm just looking for the wrong stuff).  I have a
project
that's using the Hibernate initialization using Spring to provide the
encryptor, as described here:

http://jasypt.org/hibernate3.html

The code is working, encryption and decryption performed, peachy. 
However,
when I have the system running within Tomcat I see very slow response
times
when there are multiple requests hitting encrypted columns.  If I do a
thread dump when things are performing poorly I see a number of threads
all
waiting for the same decryptor object.  Thead dump excerpt:

"http-5801-25" daemon prio=10 tid=0x0000000045ba2400 nid=0x2abd waiting
for
monitor entry [0x00000000461dd000..0x00000000461dfb10]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at
org.jasypt.encryption.pbe.StandardPBEByteEncryptor.decrypt(StandardPBEByteEncryptor.java:784)
	- waiting to lock <0x00002aaab33e0270> (a javax.crypto.Cipher)
	at
org.jasypt.encryption.pbe.StandardPBEStringEncryptor.decrypt(StandardPBEStringEncryptor.java:639)
	at
org.jasypt.hibernate.type.AbstractEncryptedAsStringType.nullSafeGet(AbstractEncryptedAsStringType.java:143)
	at org.hibernate.type.CustomType.nullSafeGet(CustomType.java:105)
	at org.hibernate.type.AbstractType.hydrate(AbstractType.java:81)
	at
org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2096)
	at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1380)
	at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1308)

Many of the threads are waiting on exactly the same object it looks like. 
I'm an admitted Spring/Hibernate/Tomcat noob, but I'm assuming what's
happening is that the encryptor being used by Hibernate is a singleton
cause
of the way Spring initializes it, and all the Tomcat threads are all
jammed
up waiting for the same object.

Am I misinterpreting what's going on, or does this seem likely?  And if
so,
is there a different way to configure these objects so that I can avoid
contention on a shared resource?  Thanks,

- Mike
  
      
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's
challenge
Build the coolest Linux based applications with Moblin SDK & win great
prizes
Grand prize is a trip for two to an Open Source event anywhere in the
world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
jasypt-users mailing list
jasypt-users@...
https://lists.sourceforge.net/lists/listinfo/jasypt-users


    

  


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
jasypt-users mailing list
jasypt-users@...
https://lists.sourceforge.net/lists/listinfo/jasypt-users

Re: Performance of StandardPBEByteEncryptor using Spring

by marcos.sousa :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi, I am build an application which will copy 180.000 rows from AS400 database (not encripted) to MySQL database (encrypted).

So, I found that jasypt is killing the performance of copy.

The application is build using Hibernate. Hibernate encrypt data when in commit phase. So, in this time it take long time running.

As an workaround, I tried to introduce an ExecutorService pool to encrypt manually in parallel.

But, jasypt put all thread waiting for the same object.

I tried some of daniel is workaround (which I understand a little bit) without success.

So, Mike did you have success? Can you provide your code?

For test purpose, In home I am using sql server database for simulate AS400 an MySQL. The code contain every thing necessary to start run without any problem. I will upload the project (27KB) build in eclipse IDE. Please append hibernate and jasypt lib necessary.sincssac.zip

Re: Performance of StandardPBEByteEncryptor using Spring

by marcos.sousa () :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

After checking the code of jasypt, looks like there is no issue related to jasypt.

The only problem was with encryption process itself.

Daniel, change the code of class: StandardPBEByteEncryptor to PBEParameterSpec be initialized  ONLY ONE TIME.

private PBEParameterSpec parameterSpec;

For encryption method:
        if (parameterSpec == null) {
        log.info("ONLY BECAUSE I AM NULL");
              // Create salt
                byte[] salt = this.saltGenerator.generateSalt(this.saltSizeBytes);

                /*
                 * Perform encryption using the Cipher
                 */
                parameterSpec =
                    new PBEParameterSpec(salt, this.keyObtentionIterations);
        }

For decryption method:
if (parameterSpec == null) {
        // If we are using a salt generator which specifies the salt
                // to be included into the encrypted message itself, get it from
                // there. If not, the salt is supposed to be fixed and thus the
                // salt generator can be safely asked for it again.
                byte[] salt = null;
                if (this.saltGenerator.includePlainSaltInEncryptionResults()) {
                    salt = ArrayUtils.subarray(
                            encryptedMessage, 0, this.saltSizeBytes);
                } else {
                    salt = this.saltGenerator.generateSalt(this.saltSizeBytes);
                }
               
               
                /*
                 * Perform decryption using the Cipher
                 */
                parameterSpec =
                    new PBEParameterSpec(salt, this.keyObtentionIterations);
        }

<code>    
private static final ExecutorService pool = Executors.newCachedThreadPool();

public static void main(String[] args) throws Exception {
                log.info("INI Sincronização");
                long start = Calendar.getInstance().getTimeInMillis();

                final StandardPBEStringEncryptor standardPBEStringEncryptor = new StandardPBEStringEncryptor();
                standardPBEStringEncryptor.setAlgorithm("PBEWithMD5AndDES");
                standardPBEStringEncryptor.setPassword("#!xxxxxxxx!#");
                standardPBEStringEncryptor.initialize();
               
                for (int i = 1; i <= 4; i++) {
                        pool.execute(new Runnable() {
                                public void run() {
                                        int threadID = nextThreadNum();
                                        log.info("Thread-" + threadID + " started");
                                        for (int j = 1; j <= threadID*5000; j++) {
                                                for (int k = 1; k <= 23; k++) {
                                                        String strTeste = "marcos veludos augusto de sousa (" + j + "," + k + ")";
                                                        String strEncr = standardPBEStringEncryptor.encrypt(strTeste);
                                                }
                                        }
                                        log.info("Thread-" + threadID + " finished");
                                }
                        });
                }
                log.info("Sleeping 60 seconds");
                Thread.sleep(60000);
                log.info("Started pool shutdown...");
                shutdown();
                log.info("All tasks have completed following shut down");

long end = Calendar.getInstance().getTimeInMillis();
                log.info("END Sincronizaç?o " + (end - start)/1000 + " segundos");
                System.exit(0);
        }

        private static void shutdown() {
                pool.shutdown(); // Disable new tasks from being submitted
                try {
                        // Wait a while for existing tasks to terminate
                        if (!pool.awaitTermination(TIMEOUT_TIME, TimeUnit.SECONDS)) {
                                pool.shutdownNow(); // Cancel currently executing tasks
                                // Wait a while for tasks to respond to being cancelled
                                if (!pool.awaitTermination(TIMEOUT_TIME, TimeUnit.SECONDS))
                                        log.error("Pool did not terminate");
                        }
                } catch (InterruptedException ie) {
                        // (Re-)Cancel if current thread also interrupted
                        pool.shutdownNow();
                        // Preserve interrupt status
                        Thread.currentThread().interrupt();
                }
        }
       
        /* For autonumbering anonymous threads. */
    private static int threadInitNumber = 1;
    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }
</code>