@@ -22,15 +22,62 @@ object CryptoUtils {
22
22
def y : Array [Byte ] = publicKey.asInstanceOf [ECPublicKey ].getQ.getAffineYCoord.getEncoded
23
23
}
24
24
25
+ private [crypto] class SecpPublicKeyImpl (pubKey : PublicKey ) extends SecpPublicKey {
26
+ override private [crypto] def publicKey : PublicKey = pubKey
27
+ }
28
+
25
29
// We define the constructor to SecpKeys private so that the only way to generate
26
30
// these keys is by using the methods unsafeToPublicKeyFromByteCoordinates and
27
31
// unsafeToPublicKeyFromCompressed.
28
- private object SecpPublicKey {
29
- private class SecpPublicKeyImpl (pubKey : PublicKey ) extends SecpPublicKey {
30
- override private [crypto] def publicKey : PublicKey = pubKey
32
+ object SecpPublicKey {
33
+
34
+ private [crypto] def fromPublicKey (key : PublicKey ): SecpPublicKey = new SecpPublicKeyImpl (key)
35
+
36
+ def checkECDSASignature (msg : Array [Byte ], sig : Array [Byte ], pubKey : SecpPublicKey ): Boolean = {
37
+ val ecdsaVerify = Signature .getInstance(" SHA256withECDSA" , provider)
38
+ ecdsaVerify.initVerify(pubKey.publicKey)
39
+ ecdsaVerify.update(msg)
40
+ ecdsaVerify.verify(sig)
41
+ }
42
+
43
+ def unsafeToSecpPublicKeyFromCompressed (com : Vector [Byte ]): SecpPublicKey = {
44
+ val params = ECNamedCurveTable .getParameterSpec(" secp256k1" )
45
+ val fact = KeyFactory .getInstance(" ECDSA" , provider)
46
+ val curve = params.getCurve
47
+ val ellipticCurve = EC5Util .convertCurve(curve, params.getSeed)
48
+ val point = ECPointUtil .decodePoint(ellipticCurve, com.toArray)
49
+ val params2 = EC5Util .convertSpec(ellipticCurve, params)
50
+ val keySpec = new ECPublicKeySpec (point, params2)
51
+ SecpPublicKey .fromPublicKey(fact.generatePublic(keySpec))
52
+ }
53
+
54
+ def unsafeToSecpPublicKeyFromByteCoordinates (x : Array [Byte ], y : Array [Byte ]): SecpPublicKey = {
55
+ def trimLeadingZeroes (arr : Array [Byte ], c : String ): Array [Byte ] = {
56
+ val trimmed = arr.dropWhile(_ == 0 .toByte)
57
+ require(
58
+ trimmed.length <= PUBLIC_KEY_COORDINATE_BYTE_SIZE ,
59
+ s " Expected $c coordinate byte length to be less than or equal ${PUBLIC_KEY_COORDINATE_BYTE_SIZE }, but got ${trimmed.length} bytes "
60
+ )
61
+ trimmed
62
+ }
63
+
64
+ val xTrimmed = trimLeadingZeroes(x, " x" )
65
+ val yTrimmed = trimLeadingZeroes(y, " y" )
66
+ val xInteger = BigInt (1 , xTrimmed)
67
+ val yInteger = BigInt (1 , yTrimmed)
68
+ SecpPublicKey .unsafeToSecpPublicKeyFromBigIntegerCoordinates(xInteger, yInteger)
31
69
}
32
70
33
- def fromPublicKey (key : PublicKey ): SecpPublicKey = new SecpPublicKeyImpl (key)
71
+ def unsafeToSecpPublicKeyFromBigIntegerCoordinates (x : BigInt , y : BigInt ): SecpPublicKey = {
72
+ val params = ECNamedCurveTable .getParameterSpec(" secp256k1" )
73
+ val fact = KeyFactory .getInstance(" ECDSA" , provider)
74
+ val curve = params.getCurve
75
+ val ellipticCurve = EC5Util .convertCurve(curve, params.getSeed)
76
+ val point = new ECPoint (x.bigInteger, y.bigInteger)
77
+ val params2 = EC5Util .convertSpec(ellipticCurve, params)
78
+ val keySpec = new ECPublicKeySpec (point, params2)
79
+ SecpPublicKey .fromPublicKey(fact.generatePublic(keySpec))
80
+ }
34
81
}
35
82
36
83
private val provider = new BouncyCastleProvider ()
@@ -40,19 +87,34 @@ object CryptoUtils {
40
87
41
88
trait Sha256Hash {
42
89
def bytes : Vector [Byte ]
90
+ def hexEncoded : String = bytesToHex(bytes)
43
91
}
44
92
45
93
private [crypto] case class Sha256HashImpl (bytes : Vector [Byte ]) extends Sha256Hash {
46
94
require(bytes.size == 32 )
47
95
}
48
96
49
- def sha256Hash (bArray : Array [Byte ]): Sha256Hash = {
50
- Sha256HashImpl (
51
- MessageDigest
52
- .getInstance(" SHA-256" )
53
- .digest(bArray)
54
- .toVector
55
- )
97
+ object Sha256Hash {
98
+
99
+ def fromBytes (arr : Array [Byte ]): Sha256Hash = Sha256HashImpl (arr.toVector)
100
+
101
+ def compute (bArray : Array [Byte ]): Sha256Hash = {
102
+ Sha256HashImpl (
103
+ MessageDigest
104
+ .getInstance(" SHA-256" )
105
+ .digest(bArray)
106
+ .toVector
107
+ )
108
+ }
109
+
110
+ def fromHex (hexedBytes : String ): Sha256Hash = {
111
+ val HEX_STRING_RE = " ^[0-9a-fA-F]{64}$" .r
112
+ if (HEX_STRING_RE .matches(hexedBytes)) Sha256HashImpl (hexToBytes(hexedBytes))
113
+ else
114
+ throw new IllegalArgumentException (
115
+ " The given hex string doesn't correspond to a valid SHA-256 hash encoded as string"
116
+ )
117
+ }
56
118
}
57
119
58
120
def bytesToHex (bytes : Vector [Byte ]): String = {
@@ -68,63 +130,4 @@ object CryptoUtils {
68
130
octet = firstIndex << 4 | secondIndex
69
131
} yield octet.toByte
70
132
}
71
-
72
- def hexedHash (hash : Sha256Hash ): String = {
73
- bytesToHex(hash.bytes)
74
- }
75
-
76
- def fromHex (hexedBytes : String ): Sha256Hash = {
77
- val HEX_STRING_RE = " ^[0-9a-fA-F]{64}$" .r
78
- if (HEX_STRING_RE .matches(hexedBytes)) Sha256HashImpl (hexToBytes(hexedBytes))
79
- else
80
- throw new IllegalArgumentException (
81
- " The given hex string doesn't correspond to a valid SHA-256 hash encoded as string"
82
- )
83
- }
84
-
85
- def checkECDSASignature (msg : Array [Byte ], sig : Array [Byte ], pubKey : SecpPublicKey ): Boolean = {
86
- val ecdsaVerify = Signature .getInstance(" SHA256withECDSA" , provider)
87
- ecdsaVerify.initVerify(pubKey.publicKey)
88
- ecdsaVerify.update(msg)
89
- ecdsaVerify.verify(sig)
90
- }
91
-
92
- def unsafeToSecpPublicKeyFromByteCoordinates (x : Array [Byte ], y : Array [Byte ]): SecpPublicKey = {
93
- def trimLeadingZeroes (arr : Array [Byte ], c : String ): Array [Byte ] = {
94
- val trimmed = arr.dropWhile(_ == 0 .toByte)
95
- require(
96
- trimmed.length <= PUBLIC_KEY_COORDINATE_BYTE_SIZE ,
97
- s " Expected $c coordinate byte length to be less than or equal ${PUBLIC_KEY_COORDINATE_BYTE_SIZE }, but got ${trimmed.length} bytes "
98
- )
99
- trimmed
100
- }
101
-
102
- val xTrimmed = trimLeadingZeroes(x, " x" )
103
- val yTrimmed = trimLeadingZeroes(y, " y" )
104
- val xInteger = BigInt (1 , xTrimmed)
105
- val yInteger = BigInt (1 , yTrimmed)
106
- unsafeToSecpPublicKeyFromBigIntegerCoordinates(xInteger, yInteger)
107
- }
108
-
109
- private def unsafeToSecpPublicKeyFromBigIntegerCoordinates (x : BigInt , y : BigInt ): SecpPublicKey = {
110
- val params = ECNamedCurveTable .getParameterSpec(" secp256k1" )
111
- val fact = KeyFactory .getInstance(" ECDSA" , provider)
112
- val curve = params.getCurve
113
- val ellipticCurve = EC5Util .convertCurve(curve, params.getSeed)
114
- val point = new ECPoint (x.bigInteger, y.bigInteger)
115
- val params2 = EC5Util .convertSpec(ellipticCurve, params)
116
- val keySpec = new ECPublicKeySpec (point, params2)
117
- SecpPublicKey .fromPublicKey(fact.generatePublic(keySpec))
118
- }
119
-
120
- def unsafeToSecpPublicKeyFromCompressed (com : Vector [Byte ]): SecpPublicKey = {
121
- val params = ECNamedCurveTable .getParameterSpec(" secp256k1" )
122
- val fact = KeyFactory .getInstance(" ECDSA" , provider)
123
- val curve = params.getCurve
124
- val ellipticCurve = EC5Util .convertCurve(curve, params.getSeed)
125
- val point = ECPointUtil .decodePoint(ellipticCurve, com.toArray)
126
- val params2 = EC5Util .convertSpec(ellipticCurve, params)
127
- val keySpec = new ECPublicKeySpec (point, params2)
128
- SecpPublicKey .fromPublicKey(fact.generatePublic(keySpec))
129
- }
130
133
}
0 commit comments