@@ -79,6 +79,7 @@ const I = gf([
7979 0xd7a7 , 0x3dfb , 0x0099 , 0x2b4d , 0xdf0b , 0x4fc1 , 0x2480 , 0x2b83
8080] ) ;
8181
82+
8283function set25519 ( r : GF , a : GF ) {
8384 for ( let i = 0 ; i < 16 ; i ++ ) {
8485 r [ i ] = a [ i ] | 0 ;
@@ -691,7 +692,7 @@ export function extractPublicKeyFromSecretKey(secretKey: Uint8Array): Uint8Array
691692 return new Uint8Array ( secretKey . subarray ( 32 ) ) ;
692693}
693694
694- const L = new Float64Array ( [
695+ const L = new Uint8Array ( [
695696 0xed , 0xd3 , 0xf5 , 0x5c , 0x1a , 0x63 , 0x12 , 0x58 , 0xd6 , 0x9c , 0xf7 , 0xa2 ,
696697 0xde , 0xf9 , 0xde , 0x14 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0x10
697698] ) ;
@@ -726,6 +727,16 @@ function modL(r: Uint8Array, x: Float64Array) {
726727 }
727728}
728729
730+ function iscanonical ( s : Uint8Array ) {
731+ let c = 0 ;
732+ let n = 1 ;
733+ for ( let i = 31 ; i >= 0 ; i -- ) {
734+ c |= ( ( s [ i ] - L [ i ] ) >> 8 ) & n ;
735+ n &= ( ( s [ i ] ^ L [ i ] ) - 1 ) >> 8 ;
736+ }
737+ return c !== 0 ;
738+ }
739+
729740function reduce ( r : Uint8Array ) {
730741 const x = new Float64Array ( 64 ) ;
731742 for ( let i = 0 ; i < 64 ; i ++ ) {
@@ -835,6 +846,9 @@ export function verify(publicKey: Uint8Array, message: Uint8Array, signature: Ui
835846 throw new Error ( `ed25519: signature must be ${ SIGNATURE_LENGTH } bytes` ) ;
836847 }
837848
849+ if ( ! iscanonical ( signature . subarray ( 32 ) ) ) {
850+ return false ;
851+ }
838852 if ( unpackneg ( q , publicKey ) ) {
839853 return false ;
840854 }
0 commit comments