@@ -15,21 +15,15 @@ import scala.util.Try
15
15
16
16
object CryptoUtils {
17
17
18
+ private val provider = new BouncyCastleProvider ()
19
+ Security .addProvider(provider)
20
+
18
21
implicit class SecpPublicKeyOps (pubKey : SecpPublicKey ) {
19
22
def toProto : CompressedECKeyData =
20
23
CompressedECKeyData (curve = ProtocolConstants .secpCurveName, data = ByteString .copyFrom(pubKey.compressed))
21
24
}
22
25
23
- def isSecp256k1 (key : SecpPublicKey ): Boolean = {
24
- val params = ECNamedCurveTable .getParameterSpec(" secp256k1" )
25
- val curve = params.getCurve
26
- val x = new BigInteger (1 , key.x)
27
- val y = new BigInteger (1 , key.y)
28
- Try (curve.validatePoint(x, y)).isSuccess
29
-
30
- }
31
-
32
- trait SecpPublicKey {
26
+ sealed trait SecpPublicKey {
33
27
private [crypto] def publicKey : PublicKey
34
28
def curveName : String = ProtocolConstants .secpCurveName
35
29
def compressed : Array [Byte ] = publicKey
@@ -47,73 +41,11 @@ object CryptoUtils {
47
41
override private [crypto] def publicKey : PublicKey = pubKey
48
42
}
49
43
50
- trait SecpECDSASignature {
51
- def bytes : Array [Byte ]
52
- }
53
- private [crypto] case class SecpECDSASignatureImpl (bytes : Array [Byte ]) extends SecpECDSASignature
54
-
55
- object SecpECDSASignature {
56
- def fromBytes (bytes : Array [Byte ]): SecpECDSASignature = SecpECDSASignatureImpl (bytes)
57
- }
58
-
59
- object SecpPrivateKey {
60
- def unsafefromBytesCompressed (bytes : Array [Byte ]): SecpPrivateKey = SecpPrivateKeyImpl (bytes)
61
- }
62
-
63
- trait SecpPrivateKey {
64
- private [crypto] def bytes : Array [Byte ]
65
- private [crypto] def privateKey : PrivateKey
66
- def getEncoded : Array [Byte ]
67
- }
68
- private [crypto] case class SecpPrivateKeyImpl (bytes : Array [Byte ]) extends SecpPrivateKey {
69
- override def getEncoded : Array [Byte ] = {
70
- privateKey
71
- .asInstanceOf [ECPrivateKey ]
72
- .getD
73
- .toByteArray
74
- .dropWhile(_ == 0 )
75
- }
76
-
77
- override def privateKey : PrivateKey = {
78
- val ecParameterSpec = ECNamedCurveTable .getParameterSpec(" secp256k1" )
79
- val ecNamedCurveSpec : ECParameterSpec = new ECNamedCurveSpec (
80
- ecParameterSpec.getName,
81
- ecParameterSpec.getCurve,
82
- ecParameterSpec.getG,
83
- ecParameterSpec.getN
84
- )
85
- val bigInt = new BigInteger (1 , bytes)
86
- val spec = new ECPrivateKeySpec (bigInt, ecNamedCurveSpec)
87
- val keyFactory = KeyFactory .getInstance(" EC" , provider)
88
- keyFactory.generatePrivate(spec)
89
- }
90
- }
91
-
92
- object SecpECDSA {
93
- def signBytes (msg : Array [Byte ], privateKey : SecpPrivateKey ): SecpECDSASignature = {
94
- val signer = Signature .getInstance(" SHA256withECDSA" , provider)
95
- signer.initSign(privateKey.privateKey)
96
- signer.update(msg)
97
- SecpECDSASignatureImpl (signer.sign())
98
- }
99
- }
100
-
101
- // We define the constructor to SecpKeys private so that the only way to generate
102
- // these keys is by using the methods unsafeToPublicKeyFromByteCoordinates and
103
- // unsafeToPublicKeyFromCompressed.
104
44
object SecpPublicKey {
105
45
106
46
private [crypto] def fromPublicKey (key : PublicKey ): SecpPublicKey = new SecpPublicKeyImpl (key)
107
47
108
- // move to SecpECDSA object
109
- def checkECDSASignature (msg : Array [Byte ], sig : Array [Byte ], pubKey : SecpPublicKey ): Boolean = {
110
- val ecdsaVerify = Signature .getInstance(" SHA256withECDSA" , provider)
111
- ecdsaVerify.initVerify(pubKey.publicKey)
112
- ecdsaVerify.update(msg)
113
- ecdsaVerify.verify(sig)
114
- }
115
-
116
- def unsafeToSecpPublicKeyFromCompressed (com : Vector [Byte ]): SecpPublicKey = {
48
+ def unsafeFromCompressed (com : Vector [Byte ]): SecpPublicKey = {
117
49
val params = ECNamedCurveTable .getParameterSpec(" secp256k1" )
118
50
val fact = KeyFactory .getInstance(" ECDSA" , provider)
119
51
val curve = params.getCurve
@@ -124,12 +56,13 @@ object CryptoUtils {
124
56
SecpPublicKey .fromPublicKey(fact.generatePublic(keySpec))
125
57
}
126
58
127
- def unsafeToSecpPublicKeyFromByteCoordinates (x : Array [Byte ], y : Array [Byte ]): SecpPublicKey = {
59
+ def unsafeFromByteCoordinates (x : Array [Byte ], y : Array [Byte ]): SecpPublicKey = {
60
+ val PUBLIC_KEY_COORDINATE_BYTE_SIZE : Int = 32
128
61
def trimLeadingZeroes (arr : Array [Byte ], c : String ): Array [Byte ] = {
129
62
val trimmed = arr.dropWhile(_ == 0 .toByte)
130
63
require(
131
64
trimmed.length <= PUBLIC_KEY_COORDINATE_BYTE_SIZE ,
132
- s " Expected $c coordinate byte length to be less than or equal ${ PUBLIC_KEY_COORDINATE_BYTE_SIZE } , but got ${trimmed.length} bytes "
65
+ s " Expected $c coordinate byte length to be less than or equal $PUBLIC_KEY_COORDINATE_BYTE_SIZE, but got ${trimmed.length} bytes "
133
66
)
134
67
trimmed
135
68
}
@@ -138,10 +71,10 @@ object CryptoUtils {
138
71
val yTrimmed = trimLeadingZeroes(y, " y" )
139
72
val xInteger = BigInt (1 , xTrimmed)
140
73
val yInteger = BigInt (1 , yTrimmed)
141
- SecpPublicKey .unsafeToSecpPublicKeyFromBigIntegerCoordinates (xInteger, yInteger)
74
+ SecpPublicKey .unsafeFromBigIntegerCoordinates (xInteger, yInteger)
142
75
}
143
76
144
- def unsafeToSecpPublicKeyFromBigIntegerCoordinates (x : BigInt , y : BigInt ): SecpPublicKey = {
77
+ private def unsafeFromBigIntegerCoordinates (x : BigInt , y : BigInt ): SecpPublicKey = {
145
78
val params = ECNamedCurveTable .getParameterSpec(" secp256k1" )
146
79
val fact = KeyFactory .getInstance(" ECDSA" , provider)
147
80
val curve = params.getCurve
@@ -152,7 +85,7 @@ object CryptoUtils {
152
85
SecpPublicKey .fromPublicKey(fact.generatePublic(keySpec))
153
86
}
154
87
155
- def unsafetoPublicKeyFromUncompressed (bytes : Array [Byte ]): SecpPublicKey = {
88
+ def unsafeFromUncompressed (bytes : Array [Byte ]): SecpPublicKey = {
156
89
val PRIVATE_KEY_BYTE_SIZE : Int = 32
157
90
val pointSize = PRIVATE_KEY_BYTE_SIZE * 2 + 1
158
91
require(bytes.length == pointSize, s " Invalid public key bytes length, ${bytes.length}" )
@@ -165,18 +98,83 @@ object CryptoUtils {
165
98
166
99
val x = new BigInteger (1 , xBytes)
167
100
val y = new BigInteger (1 , yBytes)
168
- unsafeToSecpPublicKeyFromBigIntegerCoordinates(x, y)
101
+ unsafeFromBigIntegerCoordinates(x, y)
102
+ }
103
+
104
+ def isSecp256k1 (key : SecpPublicKey ): Boolean = {
105
+ val params = ECNamedCurveTable .getParameterSpec(" secp256k1" )
106
+ val curve = params.getCurve
107
+ val x = new BigInteger (1 , key.x)
108
+ val y = new BigInteger (1 , key.y)
109
+ Try (curve.validatePoint(x, y)).isSuccess
169
110
}
170
111
}
171
112
172
- private val provider = new BouncyCastleProvider ()
173
- private val PUBLIC_KEY_COORDINATE_BYTE_SIZE : Int = 32
113
+ sealed trait SecpECDSASignature {
114
+ def bytes : Array [Byte ]
115
+ }
174
116
175
- Security .addProvider(provider)
117
+ private [crypto] case class SecpECDSASignatureImpl (bytes : Array [Byte ]) extends SecpECDSASignature
118
+
119
+ object SecpECDSASignature {
120
+ def fromBytes (bytes : Array [Byte ]): SecpECDSASignature = SecpECDSASignatureImpl (bytes)
121
+ }
122
+
123
+ sealed trait SecpPrivateKey {
124
+ private [crypto] def bytes : Array [Byte ]
125
+ private [crypto] def privateKey : PrivateKey
126
+ def getEncoded : Array [Byte ]
127
+ }
128
+
129
+ private [crypto] case class SecpPrivateKeyImpl (bytes : Array [Byte ]) extends SecpPrivateKey {
130
+ override def getEncoded : Array [Byte ] = {
131
+ privateKey
132
+ .asInstanceOf [ECPrivateKey ]
133
+ .getD
134
+ .toByteArray
135
+ .dropWhile(_ == 0 )
136
+ }
176
137
177
- trait Sha256Hash {
138
+ override def privateKey : PrivateKey = {
139
+ val ecParameterSpec = ECNamedCurveTable .getParameterSpec(" secp256k1" )
140
+ val ecNamedCurveSpec : ECParameterSpec = new ECNamedCurveSpec (
141
+ ecParameterSpec.getName,
142
+ ecParameterSpec.getCurve,
143
+ ecParameterSpec.getG,
144
+ ecParameterSpec.getN
145
+ )
146
+ val bigInt = new BigInteger (1 , bytes)
147
+ val spec = new ECPrivateKeySpec (bigInt, ecNamedCurveSpec)
148
+ val keyFactory = KeyFactory .getInstance(" EC" , provider)
149
+ keyFactory.generatePrivate(spec)
150
+ }
151
+ }
152
+
153
+ object SecpPrivateKey {
154
+ def unsafeFromBytesCompressed (bytes : Array [Byte ]): SecpPrivateKey = SecpPrivateKeyImpl (bytes)
155
+ }
156
+
157
+ object SecpECDSA {
158
+ def signBytes (msg : Array [Byte ], privateKey : SecpPrivateKey ): SecpECDSASignature = {
159
+ val signer = Signature .getInstance(" SHA256withECDSA" , provider)
160
+ signer.initSign(privateKey.privateKey)
161
+ signer.update(msg)
162
+ SecpECDSASignatureImpl (signer.sign())
163
+ }
164
+
165
+ def checkECDSASignature (msg : Array [Byte ], sig : Array [Byte ], pubKey : SecpPublicKey ): Boolean = {
166
+ val ecdsaVerify = Signature .getInstance(" SHA256withECDSA" , provider)
167
+ ecdsaVerify.initVerify(pubKey.publicKey)
168
+ ecdsaVerify.update(msg)
169
+ ecdsaVerify.verify(sig)
170
+ }
171
+ }
172
+
173
+ sealed trait Sha256Hash {
178
174
def bytes : Vector [Byte ]
179
- def hexEncoded : String = bytesToHex(bytes)
175
+ def hexEncoded : String = {
176
+ bytes.map(byte => f " ${byte & 0xff }%02x " ).mkString
177
+ }
180
178
181
179
override def equals (obj : Any ): Boolean = obj match {
182
180
case other : Sha256Hash => bytes == other.bytes
@@ -211,19 +209,15 @@ object CryptoUtils {
211
209
" The given hex string doesn't correspond to a valid SHA-256 hash encoded as string"
212
210
)
213
211
}
214
- }
215
212
216
- def bytesToHex (bytes : Vector [Byte ]): String = {
217
- bytes.map(byte => f " ${byte & 0xff }%02x " ).mkString
218
- }
219
-
220
- def hexToBytes (hex : String ): Vector [Byte ] = {
221
- val HEX_ARRAY = " 0123456789abcdef" .toCharArray
222
- for {
223
- pair <- hex.grouped(2 ).toVector
224
- firstIndex = HEX_ARRAY .indexOf(pair(0 ))
225
- secondIndex = HEX_ARRAY .indexOf(pair(1 ))
226
- octet = firstIndex << 4 | secondIndex
227
- } yield octet.toByte
213
+ private def hexToBytes (hex : String ): Vector [Byte ] = {
214
+ val HEX_ARRAY = " 0123456789abcdef" .toCharArray
215
+ for {
216
+ pair <- hex.grouped(2 ).toVector
217
+ firstIndex = HEX_ARRAY .indexOf(pair(0 ))
218
+ secondIndex = HEX_ARRAY .indexOf(pair(1 ))
219
+ octet = firstIndex << 4 | secondIndex
220
+ } yield octet.toByte
221
+ }
228
222
}
229
223
}
0 commit comments