Re: Please review EdDSA API

2018-07-26 Thread Adam Petcher

On 7/26/2018 5:05 PM, Michael StJohns wrote:

The test vectors will not pass, because they are calling the byte 
array from which the private key and the signing value are derived as 
the private key.


However, each and every signature generated by the above approach 
(e.g. using a *real* private key and a signing value downstream 
derived from that private key) *will* verify, and each and every 
signature by that private key over the same data using the above 
approach will produce identical signatures.




I've stated in the JEP[1] that the goal of this effort is an 
implementation of EdDSA as described in the RFC. What you are proposing 
is a slightly different key generation and signing procedure. The fact 
that the signatures will still verify is not sufficient to convince me 
that the procedures that you are proposing offer the same security as 
the ones in the RFC.


I understand that you don't like the fact that I am representing the 
private key value as a byte array instead of an integer. If you can come 
up with an alternative representation that still allows the same 
functions that are specified in the RFC, then I will consider it.



[1] https://bugs.openjdk.java.net/browse/JDK-8199231


Re: Please review EdDSA API

2018-07-26 Thread Michael StJohns

On 7/26/2018 4:24 PM, Adam Petcher wrote:

On 7/26/2018 3:58 PM, Michael StJohns wrote:


On 7/25/2018 2:05 PM, Adam Petcher wrote:


Did you mean PrivateKey ::= OctetToInteger(random)? Setting/clearing 
bits here destroys information. If we don't prune here, then we can 
reverse this operation later to get the byte array back to give to 
the hash.


No - I meant what I wrote:

1) generate a private key from a random and store it as a big 
integer.  E.g. generate a byte array of the appropriate length (32), 
twiddle the bits as described in step 2 of section 5.1.5 of RFC8032 
and - interpreting that buffer as a little-endian encoding, save 's' 
(the secret scalar - aka - the actual private key) as a BigInteger.


That's the limit of what goes into the PrivateKey spec/interface.
2) When you do a signing, do SigningValue = 
HASH(IntegerToLittleEndianOctets(s)).
3) When done with signing, throw away the hash value - it doesn't 
need to be stored.


Does this produce the same result as the signing function described in 
sections 3.2 and 3.3 of the RFC? If I do as you suggest, will the test 
vectors in Section 7 pass? It's not obvious to me that the signing 
procedure that you are proposing is the same function.


Note that the signing value (e.g. prefix) is used as part of the 
formation of 'r' in signing, but is not recoverable from the 
signature.   s is calculated from whatever value of r you get and the 
two taken together (r,s) form the actual signature.   Note that 'prefix' 
could be a random value if you wanted non-deterministic signatures, but 
the inclusion of a fixed prefix value means that the same signature will 
be generated by the same private key over the same data.


The test vectors will not pass, because they are calling the byte array 
from which the private key and the signing value are derived as the 
private key.


However, each and every signature generated by the above approach (e.g. 
using a *real* private key and a signing value downstream derived from 
that private key) *will* verify, and each and every signature by that 
private key over the same data using the above approach will produce 
identical signatures.


Mike




Re: Please review EdDSA API

2018-07-26 Thread Adam Petcher

On 7/26/2018 3:58 PM, Michael StJohns wrote:


On 7/25/2018 2:05 PM, Adam Petcher wrote:


Did you mean PrivateKey ::= OctetToInteger(random)? Setting/clearing 
bits here destroys information. If we don't prune here, then we can 
reverse this operation later to get the byte array back to give to 
the hash.


No - I meant what I wrote:

1) generate a private key from a random and store it as a big 
integer.  E.g. generate a byte array of the appropriate length (32), 
twiddle the bits as described in step 2 of section 5.1.5 of RFC8032 
and - interpreting that buffer as a little-endian encoding, save 's' 
(the secret scalar - aka - the actual private key) as a BigInteger.


That's the limit of what goes into the PrivateKey spec/interface.
2) When you do a signing, do SigningValue = 
HASH(IntegerToLittleEndianOctets(s)).
3) When done with signing, throw away the hash value - it doesn't need 
to be stored.


Does this produce the same result as the signing function described in 
sections 3.2 and 3.3 of the RFC? If I do as you suggest, will the test 
vectors in Section 7 pass? It's not obvious to me that the signing 
procedure that you are proposing is the same function.


Re: Please review EdDSA API

2018-07-26 Thread Michael StJohns

On 7/25/2018 2:05 PM, Adam Petcher wrote:

On 7/25/2018 11:24 AM, Michael StJohns wrote:



*sigh* Private keys are big integers.  There's an associated 
parameter used in signing that the implementation described in the 
RFC (*not a standard please note*) generates from a common random 
byte array - that byte array is NOT a (or the) private key.


E.g.   Private key ::= OctetToInteger(Adjust(Left (HASH(random), 
length))) and SigningValue ::= Right(HASH(random),length).


Instead, you can get the exact same result (deterministic signatures) 
- and store a bog standard EC private key - by


PrivateKey ::= OctetToInteger(Adjust(random));


Did you mean PrivateKey ::= OctetToInteger(random)? Setting/clearing 
bits here destroys information. If we don't prune here, then we can 
reverse this operation later to get the byte array back to give to the 
hash.


No - I meant what I wrote:

1) generate a private key from a random and store it as a big integer.  
E.g. generate a byte array of the appropriate length (32), twiddle the 
bits as described in step 2 of section 5.1.5 of RFC8032 and - 
interpreting that buffer as a little-endian encoding, save 's' (the 
secret scalar - aka - the actual private key) as a BigInteger.


That's the limit of what goes into the PrivateKey spec/interface.
2) When you do a signing, do SigningValue = 
HASH(IntegerToLittleEndianOctets(s)).
3) When done with signing, throw away the hash value - it doesn't need 
to be stored.


The *only* important characteristics of the signing value are a) it's 
confidential, and b) it's the same for each signature.  It could even be 
a random value generated and stored at the same time as the private key 
- but why?







SigningValue ::= HASH (IntegerToOctet(PrivateKey)); // signing value 
may be regenerated at any time and need not be stored in the 
ECPrivateKey class.


With the modification above, I agree that this would give the value 
that can be split in half to produce the scalar value (after pruning 
and interpreting as an integer) and the prefix that is used in signing.


I think there may be some issues with this approach, but we need to 
start by agreeing on what you are proposing. Can you confirm that my 
understanding of your proposal is correct, or else clarify it for me?


What I'm trying to get to is make the java interfaces for EC private 
keys consistent regardless of which of the curve flavor you want to 
use.   In each and every case, looking behind the specified external 
representation, the scalar 's' can be represented as a BigInteger. 
Internal representation IN A SPECIFIC IMPLEMENTATION might use little 
endian internally, but that's irrelevant here for the purposes of java 
interfaces.    (At least in my opinion).


Later, Mike




Re: Please review EdDSA API

2018-07-25 Thread Adam Petcher

On 7/25/2018 11:24 AM, Michael StJohns wrote:



*sigh* Private keys are big integers.  There's an associated parameter 
used in signing that the implementation described in the RFC (*not a 
standard please note*) generates from a common random byte array - 
that byte array is NOT a (or the) private key.


E.g.   Private key ::= OctetToInteger(Adjust(Left (HASH(random), 
length))) and SigningValue ::= Right(HASH(random),length).


Instead, you can get the exact same result (deterministic signatures) 
- and store a bog standard EC private key - by


PrivateKey ::= OctetToInteger(Adjust(random));


Did you mean PrivateKey ::= OctetToInteger(random)? Setting/clearing 
bits here destroys information. If we don't prune here, then we can 
reverse this operation later to get the byte array back to give to the 
hash.




SigningValue ::= HASH (IntegerToOctet(PrivateKey)); // signing value 
may be regenerated at any time and need not be stored in the 
ECPrivateKey class.


With the modification above, I agree that this would give the value that 
can be split in half to produce the scalar value (after pruning and 
interpreting as an integer) and the prefix that is used in signing.


I think there may be some issues with this approach, but we need to 
start by agreeing on what you are proposing. Can you confirm that my 
understanding of your proposal is correct, or else clarify it for me?


Re: Please review EdDSA API

2018-07-25 Thread Michael StJohns

On 7/25/2018 10:29 AM, Adam Petcher wrote:
2) Similar to X25519/X448, private keys are byte arrays, and public 
keys coordinates. Though we can't get by with a single BigInteger 
coordinate for EdDSA, so I am using the new EdPoint class to hold the 
coordinates.


*sigh* Private keys are big integers.  There's an associated parameter 
used in signing that the implementation described in the RFC (*not a 
standard please note*) generates from a common random byte array - that 
byte array is NOT a (or the) private key.


E.g.   Private key ::= OctetToInteger(Adjust(Left (HASH(random), 
length))) and SigningValue ::= Right(HASH(random),length).


Instead, you can get the exact same result (deterministic signatures) - 
and store a bog standard EC private key - by


PrivateKey ::= OctetToInteger(Adjust(random));

SigningValue ::= HASH (IntegerToOctet(PrivateKey)); // signing value may 
be regenerated at any time and need not be stored in the ECPrivateKey class.


Adjust twiddles the bits in the byte array to make the byte array a 
valid little-endian private key before encoding for this set of curves.  
OctetToInteger turns that byte array into a BigInteger.


At this point in time, you've got the correct values to do your point 
math using common libraries if you don't happen to have implemented 
exactly what's in the RFC.



I know the above is a losing argument, but seriously, do we really need 
two new groups of EC classes simply because someone wrote an RFC that 
didn't consider existing representational structures?


Or will it be three or more?


Later, Mike




Re: Please review EdDSA API

2018-07-25 Thread Adam Petcher

+core-libs-dev for additional API expertise.


On 7/25/2018 10:29 AM, Adam Petcher wrote:
The draft CSR[1] for the EdDSA API[2] is ready for review. Please take 
a look and send me any feedback you may have. Here are a few 
high-level notes to explain the API:


1) Where possible, this API is similar to the API for X25519/X448. To 
get the complete background/motivation for the API design, you can 
review the discussion[3] on this topic.
2) Similar to X25519/X448, private keys are byte arrays, and public 
keys coordinates. Though we can't get by with a single BigInteger 
coordinate for EdDSA, so I am using the new EdPoint class to hold the 
coordinates.
3) EdDSA has multiple signature modes defined in the RFC[4], including 
some that "prehash" the input before signing. The draft API uses the 
EdDSAParameterSpec class to specify parameters of these modes. The 
standard does not allow an arbitrary choice of prehash function, so 
the API for EdDSA does not support algorithm names like 
"SHA256withEdDSA".


[1] https://wiki.openjdk.java.net/display/csr/Main
[2] https://bugs.openjdk.java.net/browse/JDK-8190219
[3] 
http://mail.openjdk.java.net/pipermail/security-dev/2017-September/016325.html

[4] https://tools.ietf.org/html/rfc8032