<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>2025s on Mika Tuupola</title>
    <link>https://www.appelsiini.net/2025/</link>
    <description>Recent content in 2025s on Mika Tuupola</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Wed, 24 Dec 2025 00:00:00 +0000</lastBuildDate>
    
	<atom:link href="https://www.appelsiini.net/2025/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Citizens&#39; Initiatives Not So Private</title>
      <link>https://www.appelsiini.net/2025/citizens-initiatives-not-so-private/</link>
      <pubDate>Wed, 24 Dec 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.appelsiini.net/2025/citizens-initiatives-not-so-private/</guid>
      <description>&lt;p&gt;&lt;img src=&#34;https://www.appelsiini.net/img/2025/liu-shaoqi-1280.jpg&#34; alt=&#34;Liu Shaoqi being subjected to public criticism and humiliation during the Cultural Revolution.&#34;&gt;
&lt;i&gt;&lt;small&gt;
&lt;a href=&#34;https://commons.wikimedia.org/wiki/File:Liu_shaoqi.jpg&#34;&gt;&amp;ldquo;Liu Shaoqi subjected to public criticism&amp;rdquo;&lt;/a&gt;
by Unknown Author is in the
&lt;a href=&#34;https://commons.wikimedia.org/wiki/Template:PD-China&#34;&gt;Public Domain&lt;/a&gt;,
via &lt;a href=&#34;https://commons.wikimedia.org/&#34;&gt;Wikimedia Commons&lt;/a&gt;.
&lt;/small&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Finland&amp;rsquo;s leading daily newspaper &lt;a href=&#34;https://grokipedia.com/page/Helsingin_Sanomat&#34;&gt;Helsingin Sanomat&lt;/a&gt; recently wrote a hit piece against people who had supported citizens&amp;rsquo; initiatives which the newspaper considers verboten. These included initiatives such as banning political strikes or Extinction Rebellion. One initiative was asking for budget cuts to &lt;a href=&#34;https://grokipedia.com/page/Yle&#34;&gt;YLE&lt;/a&gt; which is the Finnish equivalent of BBC with similar problems to the BBC.&lt;/p&gt;
&lt;p&gt;For many, the phone call from a journalist and having their photo together with their employer published in the newspaper came as a surprise. After all the &lt;a href=&#34;https://kansalaisaloite.fi/&#34;&gt;kansalaisaloite.fi&lt;/a&gt; service &lt;a href=&#34;https://www.kansalaisaloite.fi/fi/ohjeet/henkilotietojen-suoja-ja-tietoturva&#34;&gt;advertises&lt;/a&gt; itself like this.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;ldquo;The system does not store the social security number of the person signing a statement of support. For each statement of support, an initiative specific oneway hash is calculated using the personal identity number, which securely prevents the same initiative from being supported multiple times. Based on this information, &lt;strong&gt;it is not possible to determine which different initiatives an individual person has supported in the service&lt;/strong&gt;. The data of the statements of support are stored in the database strongly encrypted. The actions of the system&amp;rsquo;s administrators are recorded in a log.&amp;rdquo;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So how was the article possible? Let&amp;rsquo;s look at the &lt;a href=&#34;https://github.com/solita/kansalaisaloite/&#34;&gt;code&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;the-hash&#34;&gt;The Hash&lt;/h2&gt;
&lt;p&gt;The FAQ claims that service uses a oneway hash for storing the personal identity number ie. SSN. This seems to be &lt;a href=&#34;https://github.com/solita/kansalaisaloite/blob/205b6ba4f93660edeb54daa00c1338119d20ad6f/src/main/java/fi/om/initiative/service/EncryptionService.java#L76-L86&#34;&gt;true&lt;/a&gt;. The hash is created by first concatenating the initiative id, SSN and a salt. This concatenation is then hashed with SHA256. The hash is a binary so it is converted to a base64 string before saving to the database.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; String &lt;span style=&#34;color:#a6e22e&#34;&gt;initiativeSupportHash&lt;/span&gt;(Long initiativeId, String ssn) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Assert.&lt;span style=&#34;color:#a6e22e&#34;&gt;notNull&lt;/span&gt;(initiativeId, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;initiativeId&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Assert.&lt;span style=&#34;color:#a6e22e&#34;&gt;hasText&lt;/span&gt;(ssn, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ssn&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    StringBuilder message &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; StringBuilder(256)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#a6e22e&#34;&gt;append&lt;/span&gt;(initiativeId).&lt;span style=&#34;color:#a6e22e&#34;&gt;append&lt;/span&gt;(MAC_DELIM)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#a6e22e&#34;&gt;append&lt;/span&gt;(ssn).&lt;span style=&#34;color:#a6e22e&#34;&gt;append&lt;/span&gt;(MAC_DELIM)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#a6e22e&#34;&gt;append&lt;/span&gt;(password);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; base64Encode(sha256(message.&lt;span style=&#34;color:#a6e22e&#34;&gt;toString&lt;/span&gt;(), DEFAULT_ENCODING), DEFAULT_ENCODING);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So far so good. This prevents duplicate votes while keeping the actual SSN private. However, when you have access to the secret key, you could brute-force the SSN from the hashes. This would not take too long with modern hardware.&lt;/p&gt;
&lt;h2 id=&#34;the-database&#34;&gt;The Database&lt;/h2&gt;
&lt;p&gt;Looking at the &lt;a href=&#34;https://github.com/solita/kansalaisaloite/blob/master/etc/schema/01_schema.sql&#34;&gt;schema&lt;/a&gt; there are three interesting columns: &lt;code&gt;initiative_id&lt;/code&gt;, &lt;code&gt;support_id&lt;/code&gt; and &lt;code&gt;details&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;create&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;table&lt;/span&gt; support_vote (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    initiative_id bigint &lt;span style=&#34;color:#66d9ef&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;NULL&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;-- base64(sha256(initiative_id &amp;amp; ssn &amp;amp; sharedSecret))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    support_id varchar(&lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;NULL&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;-- aes( name &amp;amp; birthDate &amp;amp; municipality)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    details varchar(&lt;span style=&#34;color:#ae81ff&#34;&gt;4096&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;NULL&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    created &lt;span style=&#34;color:#66d9ef&#34;&gt;timestamp&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;NOT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;NULL&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;DEFAULT&lt;/span&gt; now(),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    batch_id bigint,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;PRIMARY&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;KEY&lt;/span&gt; (initiative_id, supportId),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;FOREIGN&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;KEY&lt;/span&gt; (initiative_id) &lt;span style=&#34;color:#66d9ef&#34;&gt;REFERENCES&lt;/span&gt; initiative(id),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;FOREIGN&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;KEY&lt;/span&gt; (batch_id) &lt;span style=&#34;color:#66d9ef&#34;&gt;REFERENCES&lt;/span&gt; support_vote_batch(id)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;initiative_id&lt;/code&gt; column is the initiative being supported. The hash from above is saved to &lt;code&gt;support_id&lt;/code&gt; column. The most interesting part is the &lt;code&gt;details&lt;/code&gt; column. It contains &lt;a href=&#34;https://github.com/solita/kansalaisaloite/blob/master/src/main/java/fi/om/initiative/service/SupportVoteServiceImpl.java#L148-L170&#34;&gt;the full name, date of birth and home municipality&lt;/a&gt; of the person casting the vote.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; String &lt;span style=&#34;color:#a6e22e&#34;&gt;buildVoteDetails&lt;/span&gt;(User user, Locale locale, DateTime now) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; StringBuilder(128)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Last name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#a6e22e&#34;&gt;append&lt;/span&gt;(user.&lt;span style=&#34;color:#a6e22e&#34;&gt;getLastName&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#a6e22e&#34;&gt;append&lt;/span&gt;(VRK_CSV_DELIM)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// First names&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#a6e22e&#34;&gt;append&lt;/span&gt;(user.&lt;span style=&#34;color:#a6e22e&#34;&gt;getFirstNames&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#a6e22e&#34;&gt;append&lt;/span&gt;(VRK_CSV_DELIM)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// DateOf Birth&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#a6e22e&#34;&gt;append&lt;/span&gt;(user.&lt;span style=&#34;color:#a6e22e&#34;&gt;getDateOfBirth&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;toString&lt;/span&gt;(VRK_DTF))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#a6e22e&#34;&gt;append&lt;/span&gt;(VRK_CSV_DELIM)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Home municipality&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#a6e22e&#34;&gt;append&lt;/span&gt;(user.&lt;span style=&#34;color:#a6e22e&#34;&gt;getHomeMunicipality&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;getTranslation&lt;/span&gt;(locale))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#a6e22e&#34;&gt;append&lt;/span&gt;(VRK_CSV_DELIM)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Voting time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#a6e22e&#34;&gt;append&lt;/span&gt;(now.&lt;span style=&#34;color:#a6e22e&#34;&gt;toString&lt;/span&gt;(VRK_DTF))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#a6e22e&#34;&gt;toString&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;At least it is &lt;a href=&#34;https://github.com/solita/kansalaisaloite/blob/205b6ba4f93660edeb54daa00c1338119d20ad6f/src/main/java/fi/om/initiative/service/EncryptionService.java#L59-L74&#34;&gt;encrypted with AES&lt;/a&gt; before saving to the database.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;EncryptionService&lt;/span&gt;(String password, String vetumaSharedSecret, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; secureRandomReseedInterval, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; encryptorPoolSize) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (Strings.&lt;span style=&#34;color:#a6e22e&#34;&gt;isNullOrEmpty&lt;/span&gt;(password)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; IllegalArgumentException(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;registeredUserSecret was null or empty&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;vetumaSharedSecret&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; vetumaSharedSecret;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;password&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; password;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;secureRandomReseedInterval&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; secureRandomReseedInterval;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    aesEncryptor &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; PooledPBEStringEncryptor();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    aesEncryptor.&lt;span style=&#34;color:#a6e22e&#34;&gt;setProvider&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; BouncyCastleProvider());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    aesEncryptor.&lt;span style=&#34;color:#a6e22e&#34;&gt;setAlgorithm&lt;/span&gt;(DEFAULT_ALGORITHM);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    aesEncryptor.&lt;span style=&#34;color:#a6e22e&#34;&gt;setPassword&lt;/span&gt;(password);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    aesEncryptor.&lt;span style=&#34;color:#a6e22e&#34;&gt;setKeyObtentionIterations&lt;/span&gt;(DEFAULT_KEY_OBTENTION_ITERATIONS);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    aesEncryptor.&lt;span style=&#34;color:#a6e22e&#34;&gt;setPoolSize&lt;/span&gt;(encryptorPoolSize);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; String &lt;span style=&#34;color:#a6e22e&#34;&gt;encrypt&lt;/span&gt;(String message) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Add encryptor id to encrypted message&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; StringBuilder(message.&lt;span style=&#34;color:#a6e22e&#34;&gt;length&lt;/span&gt;() &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; 2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#a6e22e&#34;&gt;append&lt;/span&gt;(DEFAULT_ENCRYPTOR_ID)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .&lt;span style=&#34;color:#a6e22e&#34;&gt;append&lt;/span&gt;(aesEncryptor.&lt;span style=&#34;color:#a6e22e&#34;&gt;encrypt&lt;/span&gt;(message)).&lt;span style=&#34;color:#a6e22e&#34;&gt;toString&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Observant readers have probably already spotted the problem.&lt;/p&gt;
&lt;p&gt;No, it is not the fact that only &lt;a href=&#34;https://github.com/solita/kansalaisaloite/blob/master/src/main/java/fi/om/initiative/service/EncryptionService.java#L37&#34;&gt;one PBKDF iteration&lt;/a&gt; is used for key derivation. It is the fact users&amp;rsquo; full name, date of birth and home municipality are saved in the same row in the same database table as the actual vote. You do not even need the SSN to find all the initiatives an individual person has supported in the service. You just query by the name and birthday.&lt;/p&gt;
&lt;p&gt;Yeah, if nitpicking the sentence &lt;em&gt;&amp;ldquo;Based on this information, it is not possible to determine which different initiatives an individual person has supported in the service&amp;rdquo;&lt;/em&gt; is technically correct since &lt;em&gt;&lt;strong&gt;&amp;ldquo;this information&amp;rdquo;&lt;/strong&gt;&lt;/em&gt; points to the SSN. It is still misleading because you can easily find the different initiatives supported by each individual.&lt;/p&gt;
&lt;h1 id=&#34;say-what-now&#34;&gt;Say what now?&lt;/h1&gt;
&lt;p&gt;To be fair the website also states the following.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“The names of the signatories of the statements of support are not published at any stage on the Kansalaisaloite.fi service.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Which is technically correct since names have not been published on Kansalaisaloite.fi. Instead, they were published in Helsingin Sanomat.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“The organizers of a citizens’ initiative may only disclose information regarding the signatories to the Digital and Population Data Services Agency. If the Digital and Population Data Services Agency confirms that a citizens’ initiative has collected at least 50,000 statements of support, the Agency may disclose information from the statements; in other words, the information in its possession becomes public. If, according to the decision, there is an insufficient number of statements of support, the information will not become public.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This still does not take away the fact that contrary to what is claimed, it is easy to find out all initiatives supported by each individual if you have access to the database.&lt;/p&gt;
&lt;p&gt;It is worth noting also that the code in GitHub has not been updated since 2019. It is possible that development has continued behind closed doors and obvious shortcomings have been fixed in live code. If anyone knows where I can find the live codebase let me know.&lt;/p&gt;</description>
    </item>
    
  </channel>
</rss>