1
+ use alloc:: vec:: Vec ;
1
2
use core:: ops:: { Add , AddAssign , Mul } ;
2
3
3
4
use ecdsa:: { self , hazmat:: bits2field, Error , RecoveryId , Result } ;
4
- use elliptic_curve:: PrimeCurve ;
5
+ use elliptic_curve:: { sec1 :: Tag , PrimeCurve } ;
5
6
use openvm_algebra_guest:: { DivUnsafe , IntMod , Reduce } ;
6
7
7
8
use crate :: {
@@ -25,15 +26,112 @@ pub struct PublicKey<C: IntrinsicCurve> {
25
26
point : <C as IntrinsicCurve >:: Point ,
26
27
}
27
28
28
- impl < C : IntrinsicCurve > PublicKey < C > {
29
- pub fn into_inner ( self ) -> <C as IntrinsicCurve >:: Point {
30
- self . point
29
+ impl < C : IntrinsicCurve > PublicKey < C >
30
+ where
31
+ C :: Point : WeierstrassPoint + Group + FromCompressed < Coordinate < C > > ,
32
+ Coordinate < C > : IntMod ,
33
+ for < ' a > & ' a Coordinate < C > : Mul < & ' a Coordinate < C > , Output = Coordinate < C > > ,
34
+ {
35
+ pub fn new ( point : <C as IntrinsicCurve >:: Point ) -> Self {
36
+ Self { point }
37
+ }
38
+
39
+ pub fn from_sec1_bytes ( bytes : & [ u8 ] ) -> Result < Self > {
40
+ if bytes. is_empty ( ) {
41
+ return Err ( Error :: new ( ) ) ;
42
+ }
43
+
44
+ // Validate tag
45
+ let tag = Tag :: from_u8 ( bytes[ 0 ] ) . unwrap ( ) ;
46
+
47
+ // Validate length
48
+ let expected_len = tag. message_len ( Coordinate :: < C > :: NUM_LIMBS ) ;
49
+ if bytes. len ( ) != expected_len {
50
+ return Err ( Error :: new ( ) ) ;
51
+ }
52
+
53
+ match tag {
54
+ Tag :: Identity => {
55
+ let point = <<C as IntrinsicCurve >:: Point as WeierstrassPoint >:: IDENTITY ;
56
+ Ok ( Self { point } )
57
+ }
58
+
59
+ Tag :: CompressedEvenY | Tag :: CompressedOddY => {
60
+ let x = Coordinate :: < C > :: from_be_bytes ( & bytes[ 1 ..] ) ;
61
+ let rec_id = bytes[ 0 ] & 1 ;
62
+ let point = FromCompressed :: decompress ( x, & rec_id) ;
63
+ Ok ( Self { point } )
64
+ }
65
+
66
+ Tag :: Uncompressed => {
67
+ let ( x_bytes, y_bytes) = bytes[ 1 ..] . split_at ( Coordinate :: < C > :: NUM_LIMBS ) ;
68
+ let x = Coordinate :: < C > :: from_be_bytes ( x_bytes) ;
69
+ let y = Coordinate :: < C > :: from_be_bytes ( y_bytes) ;
70
+ let point = <C as IntrinsicCurve >:: Point :: from_xy ( x, y) . unwrap ( ) ;
71
+ Ok ( Self { point } )
72
+ }
73
+
74
+ _ => Err ( Error :: new ( ) ) ,
75
+ }
76
+ }
77
+
78
+ pub fn to_sec1_bytes ( & self , compress : bool ) -> Vec < u8 > {
79
+ if self . point . is_identity ( ) {
80
+ return vec ! [ 0x00 ] ;
81
+ }
82
+
83
+ let ( x, y) = self . point . clone ( ) . into_coords ( ) ;
84
+
85
+ if compress {
86
+ let mut bytes = Vec :: < u8 > :: with_capacity ( 1 + Coordinate :: < C > :: NUM_LIMBS ) ;
87
+ let tag = if y. as_le_bytes ( ) [ 0 ] & 1 == 1 {
88
+ Tag :: CompressedOddY
89
+ } else {
90
+ Tag :: CompressedEvenY
91
+ } ;
92
+ bytes. push ( tag. into ( ) ) ;
93
+ bytes. extend_from_slice ( x. to_be_bytes ( ) . as_ref ( ) ) ;
94
+ bytes
95
+ } else {
96
+ let mut bytes = Vec :: < u8 > :: with_capacity ( 1 + Coordinate :: < C > :: NUM_LIMBS * 2 ) ;
97
+ bytes. push ( Tag :: Uncompressed . into ( ) ) ;
98
+ bytes. extend_from_slice ( x. to_be_bytes ( ) . as_ref ( ) ) ;
99
+ bytes. extend_from_slice ( y. to_be_bytes ( ) . as_ref ( ) ) ;
100
+ bytes
101
+ }
102
+ }
103
+
104
+ pub fn as_affine ( & self ) -> & <C as IntrinsicCurve >:: Point {
105
+ & self . point
31
106
}
32
107
}
33
108
34
- impl < C : IntrinsicCurve > VerifyingKey < C > {
109
+ impl < C : IntrinsicCurve > VerifyingKey < C >
110
+ where
111
+ C :: Point : WeierstrassPoint + Group + FromCompressed < Coordinate < C > > ,
112
+ Coordinate < C > : IntMod ,
113
+ for < ' a > & ' a Coordinate < C > : Mul < & ' a Coordinate < C > , Output = Coordinate < C > > ,
114
+ {
115
+ pub fn new ( public_key : PublicKey < C > ) -> Self {
116
+ Self { inner : public_key }
117
+ }
118
+
119
+ pub fn from_sec1_bytes ( bytes : & [ u8 ] ) -> Result < Self > {
120
+ let public_key = PublicKey :: < C > :: from_sec1_bytes ( bytes) ?;
121
+ Ok ( Self :: new ( public_key) )
122
+ }
123
+
124
+ pub fn from_affine ( point : <C as IntrinsicCurve >:: Point ) -> Result < Self > {
125
+ let public_key = PublicKey :: < C > :: new ( point) ;
126
+ Ok ( Self :: new ( public_key) )
127
+ }
128
+
129
+ pub fn to_sec1_bytes ( & self , compress : bool ) -> Vec < u8 > {
130
+ self . inner . to_sec1_bytes ( compress)
131
+ }
132
+
35
133
pub fn as_affine ( & self ) -> & <C as IntrinsicCurve >:: Point {
36
- & self . inner . point
134
+ self . inner . as_affine ( )
37
135
}
38
136
}
39
137
0 commit comments