1+ from .math import Math
12from .utils .integer import RandomInteger
2- from .utils .compatibility import *
3- from .utils .binary import BinaryAscii
4- from .utils .der import fromPem , removeSequence , removeInteger , removeObject , removeOctetString , removeConstructed , toPem , encodeSequence , encodeInteger , encodeBitString , encodeOid , encodeOctetString , encodeConstructed
3+ from .utils .pem import getPemContent , createPem
4+ from .utils .binary import hexFromByteString , byteStringFromHex , intFromHex , base64FromByteString , byteStringFromBase64
5+ from .utils .der import hexFromInt , parse , encodeConstructed , DerFieldType , encodePrimitive
6+ from .curve import secp256k1 , getCurveByOid
57from .publicKey import PublicKey
6- from .curve import secp256k1 , curvesByOid , supportedCurves
7- from .math import Math
8-
9- hexAt = "\x00 "
108
119
1210class PrivateKey :
@@ -27,69 +25,48 @@ def publicKey(self):
2725 return PublicKey (point = publicPoint , curve = curve )
2826
2927 def toString (self ):
30- return BinaryAscii . stringFromNumber ( number = self .secret , length = self . curve . length () )
28+ return hexFromInt ( self .secret )
3129
3230 def toDer (self ):
33- encodedPublicKey = self .publicKey ().toString (encoded = True )
34-
35- return encodeSequence (
36- encodeInteger (1 ),
37- encodeOctetString (self .toString ()),
38- encodeConstructed (0 , encodeOid (* self .curve .oid )),
39- encodeConstructed (1 , encodeBitString (encodedPublicKey )),
31+ publicKeyString = self .publicKey ().toString (encoded = True )
32+ hexadecimal = encodeConstructed (
33+ encodePrimitive (DerFieldType .integer , 1 ),
34+ encodePrimitive (DerFieldType .octetString , hexFromInt (self .secret )),
35+ encodePrimitive (DerFieldType .oidContainer , encodePrimitive (DerFieldType .object , self .curve .oid )),
36+ encodePrimitive (DerFieldType .publicKeyPointContainer , encodePrimitive (DerFieldType .bitString , publicKeyString ))
4037 )
38+ return byteStringFromHex (hexadecimal )
4139
4240 def toPem (self ):
43- return toPem (der = toBytes (self .toDer ()), name = "EC PRIVATE KEY" )
41+ der = self .toDer ()
42+ return createPem (content = base64FromByteString (der ), template = _pemTemplate )
4443
4544 @classmethod
4645 def fromPem (cls , string ):
47- privateKeyPem = string [ string . index ( "-----BEGIN EC PRIVATE KEY-----" ):]
48- return cls .fromDer (fromPem (privateKeyPem ))
46+ privateKeyPem = getPemContent ( pem = string , template = _pemTemplate )
47+ return cls .fromDer (byteStringFromBase64 (privateKeyPem ))
4948
5049 @classmethod
5150 def fromDer (cls , string ):
52- t , empty = removeSequence (string )
53- if len (empty ) != 0 :
54- raise Exception (
55- "trailing junk after DER private key: " +
56- BinaryAscii .hexFromBinary (empty )
57- )
58-
59- one , t = removeInteger (t )
60- if one != 1 :
61- raise Exception (
62- "expected '1' at start of DER private key, got %d" % one
63- )
64-
65- privateKeyStr , t = removeOctetString (t )
66- tag , curveOidStr , t = removeConstructed (t )
67- if tag != 0 :
68- raise Exception ("expected tag 0 in DER private key, got %d" % tag )
69-
70- oidCurve , empty = removeObject (curveOidStr )
71-
72- if len (empty ) != 0 :
73- raise Exception (
74- "trailing junk after DER private key curve_oid: %s" %
75- BinaryAscii .hexFromBinary (empty )
76- )
77-
78- if oidCurve not in curvesByOid :
79- raise Exception (
80- "unknown curve with oid %s; The following are registered: %s" % (
81- oidCurve ,
82- ", " .join ([curve .name for curve in supportedCurves ])
83- )
84- )
85-
86- curve = curvesByOid [oidCurve ]
87-
88- if len (privateKeyStr ) < curve .length ():
89- privateKeyStr = hexAt * (curve .lenght () - len (privateKeyStr )) + privateKeyStr
90-
91- return cls .fromString (privateKeyStr , curve )
51+ hexadecimal = hexFromByteString (string )
52+ privateKeyFlag , secretHex , curveData , publicKeyString = parse (hexadecimal )[0 ]
53+ if privateKeyFlag != 1 :
54+ raise Exception ("Private keys should start with a '1' flag, but a '{flag}' was found instead" .format (
55+ flag = privateKeyFlag
56+ ))
57+ curve = getCurveByOid (curveData [0 ])
58+ privateKey = cls .fromString (string = secretHex , curve = curve )
59+ if privateKey .publicKey ().toString (encoded = True ) != publicKeyString [0 ]:
60+ raise Exception ("The public key described inside the private key file doesn't match the actual public key of the pair" )
61+ return privateKey
9262
9363 @classmethod
9464 def fromString (cls , string , curve = secp256k1 ):
95- return PrivateKey (secret = BinaryAscii .numberFromString (string ), curve = curve )
65+ return PrivateKey (secret = intFromHex (string ), curve = curve )
66+
67+
68+ _pemTemplate = """
69+ -----BEGIN EC PRIVATE KEY-----
70+ {content}
71+ -----END EC PRIVATE KEY-----
72+ """
0 commit comments