I am trying to convert this java code for generating JWT token in python.
String privateKeyContent = privateKey
.replaceAll(Definitions.ApiGeneral.LINE_BREAKER, "")
.replace(Definitions.AuthProperty.PRIVATE_KEY_START, "")
.replace(Definitions.AuthProperty.PRIVATE_KEY_END, "");
PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyContent));
KeyFactory kf = KeyFactory.getInstance(Definitions.AuthProperty.RSA_KEY_FACTORY);
PrivateKey privKey = kf.generatePrivate(keySpecPKCS8);
String jwtAudUrl = System.getenv(Definitions.IamProperty.IAM_URL_KEY) + System.getenv(Definitions.IamProperty.JWT_AUD_URI_KEY);
String jwtToken = Jwts.builder()
.setAudience(jwtAudUrl)
.setSubject(serviceId)
.setIssuer(serviceId)
.setExpiration(new Date(new Date().getTime() + TimeUnit.MINUTES.toMillis(Definitions.AuthProperty.JWT_TOKEN_EXPIRY_IN_MINUTES)))
.signWith(privKey)
.compact();
Python:
import jwt
serviceID = "abc"
secret = '-----BEGIN RSA PRIVATE KEY-----MIIEogIBAAKCAQEAhstYtRbkgQkFwlVr8QjSCQqqRTDMKWHdIGRYBpXcQmvKfagId9nBA2Ygh7cOrT9g8MhxYo8U1jYmPQpv6gf3LgO/J0qspLdaAhZP6LusA/HHJBR7kjTXBsLcsEDyd8S0UioBYP3DLvtWhGIR2f4o7SH1TlE96tldV6FZKGO2NHsJrJwTd+ym0AeZe0b7QZLe43LBCTLdqk05U34jrknJliSAEbGqYg4h6nrJsKBC/0pmiQ9ptD1N/Kl4bqffMWIbZq2bPP6jFrmBLe+7yTeVMKltVbJZys4nHhyYngBtbAxynXeB2tpE8If7cK75fj42MlFgquEiEZZVSzNNmrmPOwIDAQABAoH/B18Xes/Fr0jPB9GkFYpl8hijNyV0BM9VSHA0YCfR49ABQt3tmKBP7d+n58QbCV5t7r0Hdlxcx1ouvSfU9vd4jQunaH6s8lUUlwihVhjtT0npmg+EsnoxSC1f5EOo/uPC+LtTV/qIsgkMsjCqyUEc+9rfj2jh+fXpJOGt/od1b2k2xs84MsXmSF/As7GYRdw+FLbkN64R/SGmv3NLtQdg5uvBKLuKvtQWIJBuPqgKOsJWaCVO0XaoUDQeav/nTfP0ntmF0QH9JtXYzBldhGq2FPVQRUaCuJ4YPEpXlD3FptQBlX/Wu7wXbdwDz3qyXbGqSkiaR3gN+QR+IgjG3oQxAoGBAML5M4Dg0S/yobHuCRcvpngraXGBWnCTaD0mMh/cosV0HBNdZbglwVpG8Agz9BEYIrDM777HFuB+lWUvGNMR45rObPcDqn7Qj8Uwnj775Bg0Sx09MCBds6IGce/92uPUsHPx4pj8dzCj1s3cfUKO+EaUE33bnFXcMCGh/0x0sIVXAoGBALD8H4Aph2OPQK9OOHb3ULDvrmMPrpe3xv5iSzfLt7xBIP2G0Wl+q0hzEtdEOUZGQemOtyuV5t9Jwwfh9uH9jAhk9OEvoNg3F3mQl6hjmHPd1xUNvRTqwnV+VvQnw7Aeq2TZMcAKwbXf3+p430wMsxR6m0Y7rGi0FIxWbILp0RK9AoGBAIfiPBXnGYOsOysRtb42FHQN9WgI+eoZof10IFz6XWr12Bda8Wicz5vGcsWUx9YeFxdXTQOOJ5CASEiDwW5hOlqK4YBqSqolWv3YO4Gz9i00TOFs4py8EVSr3z6ekq5UbkHwY7exxLPei/dfYuE/WSN/UfJWWyev1M+r4oz7iobzAoGAKe8S56LvWT+P6/l0l3txuvqPLxmAHKKGm69ecxHprskfr/JJm91PaBMb27VmfKgY5eXSsJkL4svvUebQQCt7CmIhQ1mtmo0zGrKPvG4cqRde5rYintogyQXuRFtHmmsp4PM1PnNOAnHQ9BU/kx1PMQL712A8MXK5i6bOfxY3W2ECgYEAp9cw3NeMSy/WcXyZoyNFUdEQiHTJGPBtELjHWRnjMU1454EkWYYPiYXUnElfxP6InxHgMNbGVsd1BUEhXOdSUS5bO/WBOOPqSh6MIGfKFuMN/9SI/Y/UZKltCD1CboTvDfmkD+opkLM6YZpW9CRT7Szn7ivdFr5KqGQZUZOwn3k=-----END RSA PRIVATE KEY-----'
due_date = datetime.now() + timedelta(minutes=10)
header = {"alg": "RS256"}
expiry = int(due_date.timestamp())
payload = {"iss": serviceID, "sub": serviceID, "exp": expiry, "aud": iam_url + "/oauth2/access_token"}
priv_rsakey = serialization.load_pem_private_key(secret.encode('utf8'), password=None, backend=default_backend())
token=jwt.encode(payload, priv_rsakey, algorithm='RS256')
However, I keep on getting this error :
ValueError: ('Could not deserialize key data. The data may be in an incorrect format, it may be encrypted with an unsupported algorithm, or it may be an unsupported key type (e.g. EC curves with explicit parameters).', [_OpenSSLErrorWithText(code=503841036, lib=60, reason=524556, reason_text=b'error:1E08010C:DECODER routines::unsupported')])
Can someone please help me with this ?
The issue is precisely identified in the error message: Your private key is incorrectly formatted. A PEM encoded key consists of the Base64 encoded body, which contains a line break after every 64 characters, and a header and footer on separate lines. Your key is missing the line breaks.
load_pem_private_key() expects at least header and footer on separate lines, but is tolerant about line breaks in the body, i.e. they are optional. So you have to pass your key e.g. like this:
secret = '-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAKCAQEAhstYtRbkgQkFwlVr8QjSCQqqRTDMKWHdIGRYBpXcQmvKfagId9nBA2Ygh7cOrT9g8MhxYo8U1jYmPQpv6gf3LgO/J0qspLdaAhZP6LusA/HHJBR7kjTXBsLcsEDyd8S0UioBYP3DLvtWhGIR2f4o7SH1TlE96tldV6FZKGO2NHsJrJwTd+ym0AeZe0b7QZLe43LBCTLdqk05U34jrknJliSAEbGqYg4h6nrJsKBC/0pmiQ9ptD1N/Kl4bqffMWIbZq2bPP6jFrmBLe+7yTeVMKltVbJZys4nHhyYngBtbAxynXeB2tpE8If7cK75fj42MlFgquEiEZZVSzNNmrmPOwIDAQABAoH/B18Xes/Fr0jPB9GkFYpl8hijNyV0BM9VSHA0YCfR49ABQt3tmKBP7d+n58QbCV5t7r0Hdlxcx1ouvSfU9vd4jQunaH6s8lUUlwihVhjtT0npmg+EsnoxSC1f5EOo/uPC+LtTV/qIsgkMsjCqyUEc+9rfj2jh+fXpJOGt/od1b2k2xs84MsXmSF/As7GYRdw+FLbkN64R/SGmv3NLtQdg5uvBKLuKvtQWIJBuPqgKOsJWaCVO0XaoUDQeav/nTfP0ntmF0QH9JtXYzBldhGq2FPVQRUaCuJ4YPEpXlD3FptQBlX/Wu7wXbdwDz3qyXbGqSkiaR3gN+QR+IgjG3oQxAoGBAML5M4Dg0S/yobHuCRcvpngraXGBWnCTaD0mMh/cosV0HBNdZbglwVpG8Agz9BEYIrDM777HFuB+lWUvGNMR45rObPcDqn7Qj8Uwnj775Bg0Sx09MCBds6IGce/92uPUsHPx4pj8dzCj1s3cfUKO+EaUE33bnFXcMCGh/0x0sIVXAoGBALD8H4Aph2OPQK9OOHb3ULDvrmMPrpe3xv5iSzfLt7xBIP2G0Wl+q0hzEtdEOUZGQemOtyuV5t9Jwwfh9uH9jAhk9OEvoNg3F3mQl6hjmHPd1xUNvRTqwnV+VvQnw7Aeq2TZMcAKwbXf3+p430wMsxR6m0Y7rGi0FIxWbILp0RK9AoGBAIfiPBXnGYOsOysRtb42FHQN9WgI+eoZof10IFz6XWr12Bda8Wicz5vGcsWUx9YeFxdXTQOOJ5CASEiDwW5hOlqK4YBqSqolWv3YO4Gz9i00TOFs4py8EVSr3z6ekq5UbkHwY7exxLPei/dfYuE/WSN/UfJWWyev1M+r4oz7iobzAoGAKe8S56LvWT+P6/l0l3txuvqPLxmAHKKGm69ecxHprskfr/JJm91PaBMb27VmfKgY5eXSsJkL4svvUebQQCt7CmIhQ1mtmo0zGrKPvG4cqRde5rYintogyQXuRFtHmmsp4PM1PnNOAnHQ9BU/kx1PMQL712A8MXK5i6bOfxY3W2ECgYEAp9cw3NeMSy/WcXyZoyNFUdEQiHTJGPBtELjHWRnjMU1454EkWYYPiYXUnElfxP6InxHgMNbGVsd1BUEhXOdSUS5bO/WBOOPqSh6MIGfKFuMN/9SI/Y/UZKltCD1CboTvDfmkD+opkLM6YZpW9CRT7Szn7ivdFr5KqGQZUZOwn3k=\n-----END RSA PRIVATE KEY-----'
or
secret = '''-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAhstYtRbkgQkFwlVr8QjSCQqqRTDMKWHdIGRYBpXcQmvKfagId9nBA2Ygh7cOrT9g8MhxYo8U1jYmPQpv6gf3LgO/J0qspLdaAhZP6LusA/HHJBR7kjTXBsLcsEDyd8S0UioBYP3DLvtWhGIR2f4o7SH1TlE96tldV6FZKGO2NHsJrJwTd+ym0AeZe0b7QZLe43LBCTLdqk05U34jrknJliSAEbGqYg4h6nrJsKBC/0pmiQ9ptD1N/Kl4bqffMWIbZq2bPP6jFrmBLe+7yTeVMKltVbJZys4nHhyYngBtbAxynXeB2tpE8If7cK75fj42MlFgquEiEZZVSzNNmrmPOwIDAQABAoH/B18Xes/Fr0jPB9GkFYpl8hijNyV0BM9VSHA0YCfR49ABQt3tmKBP7d+n58QbCV5t7r0Hdlxcx1ouvSfU9vd4jQunaH6s8lUUlwihVhjtT0npmg+EsnoxSC1f5EOo/uPC+LtTV/qIsgkMsjCqyUEc+9rfj2jh+fXpJOGt/od1b2k2xs84MsXmSF/As7GYRdw+FLbkN64R/SGmv3NLtQdg5uvBKLuKvtQWIJBuPqgKOsJWaCVO0XaoUDQeav/nTfP0ntmF0QH9JtXYzBldhGq2FPVQRUaCuJ4YPEpXlD3FptQBlX/Wu7wXbdwDz3qyXbGqSkiaR3gN+QR+IgjG3oQxAoGBAML5M4Dg0S/yobHuCRcvpngraXGBWnCTaD0mMh/cosV0HBNdZbglwVpG8Agz9BEYIrDM777HFuB+lWUvGNMR45rObPcDqn7Qj8Uwnj775Bg0Sx09MCBds6IGce/92uPUsHPx4pj8dzCj1s3cfUKO+EaUE33bnFXcMCGh/0x0sIVXAoGBALD8H4Aph2OPQK9OOHb3ULDvrmMPrpe3xv5iSzfLt7xBIP2G0Wl+q0hzEtdEOUZGQemOtyuV5t9Jwwfh9uH9jAhk9OEvoNg3F3mQl6hjmHPd1xUNvRTqwnV+VvQnw7Aeq2TZMcAKwbXf3+p430wMsxR6m0Y7rGi0FIxWbILp0RK9AoGBAIfiPBXnGYOsOysRtb42FHQN9WgI+eoZof10IFz6XWr12Bda8Wicz5vGcsWUx9YeFxdXTQOOJ5CASEiDwW5hOlqK4YBqSqolWv3YO4Gz9i00TOFs4py8EVSr3z6ekq5UbkHwY7exxLPei/dfYuE/WSN/UfJWWyev1M+r4oz7iobzAoGAKe8S56LvWT+P6/l0l3txuvqPLxmAHKKGm69ecxHprskfr/JJm91PaBMb27VmfKgY5eXSsJkL4svvUebQQCt7CmIhQ1mtmo0zGrKPvG4cqRde5rYintogyQXuRFtHmmsp4PM1PnNOAnHQ9BU/kx1PMQL712A8MXK5i6bOfxY3W2ECgYEAp9cw3NeMSy/WcXyZoyNFUdEQiHTJGPBtELjHWRnjMU1454EkWYYPiYXUnElfxP6InxHgMNbGVsd1BUEhXOdSUS5bO/WBOOPqSh6MIGfKFuMN/9SI/Y/UZKltCD1CboTvDfmkD+opkLM6YZpW9CRT7Szn7ivdFr5KqGQZUZOwn3k=
-----END RSA PRIVATE KEY-----'''
With this change the code works (after adding the missing iam_url and the missing import statements).
Note that PKCS8EncodedKeySpec in the Java code expects a DER encoded private key in PKCS#8 format, while in the Python code a PEM encoded private key in PKCS#1 format is applied.
A DER encoded key results from a PEM encoded key by removing header, footer and all line breaks, and Base64 decoding the rest. The Cryptography library supports the import of a DER encoded private key with load_der_private_key():
import base64
secret = base64.b64decode('MIIEogIBAAKCAQEAhstYtRbkgQkFwlVr8QjSCQqqRTDMKWHdIGRYBpXcQmvKfagId9nBA2Ygh7cOrT9g8MhxYo8U1jYmPQpv6gf3LgO/J0qspLdaAhZP6LusA/HHJBR7kjTXBsLcsEDyd8S0UioBYP3DLvtWhGIR2f4o7SH1TlE96tldV6FZKGO2NHsJrJwTd+ym0AeZe0b7QZLe43LBCTLdqk05U34jrknJliSAEbGqYg4h6nrJsKBC/0pmiQ9ptD1N/Kl4bqffMWIbZq2bPP6jFrmBLe+7yTeVMKltVbJZys4nHhyYngBtbAxynXeB2tpE8If7cK75fj42MlFgquEiEZZVSzNNmrmPOwIDAQABAoH/B18Xes/Fr0jPB9GkFYpl8hijNyV0BM9VSHA0YCfR49ABQt3tmKBP7d+n58QbCV5t7r0Hdlxcx1ouvSfU9vd4jQunaH6s8lUUlwihVhjtT0npmg+EsnoxSC1f5EOo/uPC+LtTV/qIsgkMsjCqyUEc+9rfj2jh+fXpJOGt/od1b2k2xs84MsXmSF/As7GYRdw+FLbkN64R/SGmv3NLtQdg5uvBKLuKvtQWIJBuPqgKOsJWaCVO0XaoUDQeav/nTfP0ntmF0QH9JtXYzBldhGq2FPVQRUaCuJ4YPEpXlD3FptQBlX/Wu7wXbdwDz3qyXbGqSkiaR3gN+QR+IgjG3oQxAoGBAML5M4Dg0S/yobHuCRcvpngraXGBWnCTaD0mMh/cosV0HBNdZbglwVpG8Agz9BEYIrDM777HFuB+lWUvGNMR45rObPcDqn7Qj8Uwnj775Bg0Sx09MCBds6IGce/92uPUsHPx4pj8dzCj1s3cfUKO+EaUE33bnFXcMCGh/0x0sIVXAoGBALD8H4Aph2OPQK9OOHb3ULDvrmMPrpe3xv5iSzfLt7xBIP2G0Wl+q0hzEtdEOUZGQemOtyuV5t9Jwwfh9uH9jAhk9OEvoNg3F3mQl6hjmHPd1xUNvRTqwnV+VvQnw7Aeq2TZMcAKwbXf3+p430wMsxR6m0Y7rGi0FIxWbILp0RK9AoGBAIfiPBXnGYOsOysRtb42FHQN9WgI+eoZof10IFz6XWr12Bda8Wicz5vGcsWUx9YeFxdXTQOOJ5CASEiDwW5hOlqK4YBqSqolWv3YO4Gz9i00TOFs4py8EVSr3z6ekq5UbkHwY7exxLPei/dfYuE/WSN/UfJWWyev1M+r4oz7iobzAoGAKe8S56LvWT+P6/l0l3txuvqPLxmAHKKGm69ecxHprskfr/JJm91PaBMb27VmfKgY5eXSsJkL4svvUebQQCt7CmIhQ1mtmo0zGrKPvG4cqRde5rYintogyQXuRFtHmmsp4PM1PnNOAnHQ9BU/kx1PMQL712A8MXK5i6bOfxY3W2ECgYEAp9cw3NeMSy/WcXyZoyNFUdEQiHTJGPBtELjHWRnjMU1454EkWYYPiYXUnElfxP6InxHgMNbGVsd1BUEhXOdSUS5bO/WBOOPqSh6MIGfKFuMN/9SI/Y/UZKltCD1CboTvDfmkD+opkLM6YZpW9CRT7Szn7ivdFr5KqGQZUZOwn3k=')
priv_rsakey = serialization.load_der_private_key(secret, password=None, backend=default_backend())
load_pem_private_key() and load_der_private_key() support both PKCS#8 and PKCS#1 format.
Related
I'm writting a little program using SSL sockets. A client sends values to a server and when the server gets the value it checks the client's public key to make sure he's expected to send something. So at first the server is getting all the public keys like this :
cert = f.read()
crtObj = crypto.load_certificate(crypto.FILETYPE_PEM, cert)
pubKeyObject = crtObj.get_pubkey()
pubKeyString = crypto.dump_publickey(crypto.FILETYPE_PEM,pubKeyObject)
with this method, the public key is :
b'-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7GIzek5JgfFzFCGwnx7X\ncE4QULV/9uyoGgd9HbHYyYcItEcSPU39ORXCrNQGxh09k4oFPBYntjD2gIORF8V4\n6EAC10bFaT18OuM1F/37v+K/+BuvCDTqcS9Y0CRalwPFVYB+yttvZ8fnvO2l/TxF\nsLmZh0yY/ajaHxey/ppUQycGy4xA8XD6VlWFM7+I0t/19rrLN9iMFSym/TgYpBbn\nxyZel8rMW/ACS09nSprEu1BuI+myhhej+cuy3wU8byRTwANpqHxsx5cTwp642TVx\nBKbuO8GHAzEKcrFZnrKcsXr9emWV5ouYiVzehOT4Pd3I2W8qSy6x/Ovv/iS3ojT4\ndQIDAQAB\n-----END PUBLIC KEY-----\n'
and when the server wants to get it from the socket connection like this :
test1 = writer.get_extra_info('ssl_object')
der =test1.getpeercert(binary_form=True)
test = test1.getpeercert()
cert = x509.Certificate.load(der)
pubkey= cert.public_key.unwrap()
print(pem.armor("PUBLIC KEY", pubkey.contents).decode("ASCII"))
the public key printed is :
-----BEGIN PUBLIC KEY-----
AoIBAQDsYjN6TkmB8XMUIbCfHtdwThBQtX/27KgaB30dsdjJhwi0RxI9Tf05FcKs
1AbGHT2TigU8Fie2MPaAg5EXxXjoQALXRsVpPXw64zUX/fu/4r/4G68INOpxL1jQ
JFqXA8VVgH7K229nx+e87aX9PEWwuZmHTJj9qNofF7L+mlRDJwbLjEDxcPpWVYUz
v4jS3/X2uss32IwVLKb9OBikFufHJl6Xysxb8AJLT2dKmsS7UG4j6bKGF6P5y7Lf
BTxvJFPAA2mofGzHlxPCnrjZNXEEpu47wYcDMQpysVmespyxev16ZZXmi5iJXN6E
5Pg93cjZbypLLrH86+/+JLeiNPh1AgMBAAE=
-----END PUBLIC KEY-----
So I don't know if it's a matter of format or if it's really not the same public key I'm getting... but it should be.
Sorry for the long post and thank you very much for reading.
Most(if not all) base64 encoding variants use A-Z, a-z, 0-9 characters to represent data the total is 62 character and some base64 encodings varies in the last 2 characters but most of them use + and / which will complete 64. So the above 2 keys seems to be completely different and the second key is also padded because of = sign at end. The standard base64 encoding is RFC 4648 variant which use + and / and make padding as optional not mandatory like RFC 4880 openpgp base64 encoding.
It was in fact the same keys but the way of getting it was wrong : here the right one from the ssl object :
test1 = writer.get_extra_info('ssl_object')
der =test1.getpeercert(binary_form=True)
crtObj = crypto.load_certificate(crypto.FILETYPE_ASN1, der)
pubKeyObject = crtObj.get_pubkey()
pubKeyString = crypto.dump_publickey(crypto.FILETYPE_PEM, pubKeyObject)
I've tried using my public key vs. using the private key, putting a b in front, doing 3 vs. 1 quotes vs. one quote (and many more things I see here on Stackoverflow) and I keep getting the following error:
ValueError: Could not deserialize key data.
Any ideas?
import jwt
secret_key='''MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwE...pTeoOgWZ'''
token = '''eyJraWQiOiI4NkQ4OEtmIiwiNG2Bua1WoKEI8T..._cXnyThWA'''
#public_key = '''iGaLqP6y-SJCCBq5Hv6pGDbG_SQ11MNj...Mb0jcOTmBRZA2QuYw-zHLwQ'''
payload = jwt.decode(token, secret_key, algorithms=['RS256'])
return payload
Try with the complete public key including the begin and end delimiters and use """ or ''' for a multiline string:
import jwt
token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.K71d-kndywmuxJR-SzDqTARcHJBsHezMeRtDwn4S0NMd3ZmW1LKKqoVQv8rMNam4HK6hsSmB0sqIpKfiLFn73HC1j9-fdBafZNy-9eL4cNr1ldwxj5jD6CwPMjT0mOB01liHFPiIfHDabYV2FzFEV8oaX8CxVL7_CLLv2I01NHo"
pubkey = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCcbV4zk01saMn/VzIDN7rOY8D
BTYGnH6fnYB/wTKBHme6MpuOv+4d48ZKDseP8EcTFQmmAmKeKRGJUzSJ9cN2KlND
a4y2gkEsqh8a9U/7492hVWNB6JkSPrdqrkRho9/q9gCcDlTZROY/RDuf3Y1F1riV
tiFvXvfCp75fpLceIQIDAQAB
-----END PUBLIC KEY-----"""
payload = jwt.decode(token, pubkey, algorithms=['RS256'])
print(payload)
Output:
{'sub': '1234567890', 'name': 'John Doe', 'iat': 1516239022}
(no worries about the key, I just created it online just for demonstration purpose)
I figured it out. My public key above wasn't actually a public key. It is a RSA key modulus. I had to use this tutorial to take this RSA key modulus and the exponent to generate a public key. When i did this, then the JWT.decode functionality worked just fine.
Thanks #jps for your help!
I have a method as below that sign provided data:
def sign_data(self, private_key_loc, data):
"""
param: private_key_loc Path to your private key
param: package Data to be signed
return: base64 encoded signature
"""
key = open(private_key_loc, "r").read()
print(key)
rsakey = RSA.importKey(key) # This raise an error!!!!
print(rsakey)
signer = PKCS1_v1_5.new(rsakey)
digest = SHA256.new()
# It's being assumed the data is base64 encoded, so it's decoded before updating the digest
digest.update(data)
sign = signer.sign(digest)
return b64encode(sign)
The format of the private key is as below:
<RSAKeyValue><Modulus>nEWZmLeK0zgEWysFFcpcT6lnYpzYcXFf+r43wD73ko+CjR5EmwDsmlKqKS5y3rpIHQrj+xE+yiNGlcPFNwFl3cCcHPkeI0hqaPPYxE2XeP6Wa0keegny2AWWK2Cuv61YHVz4XgxTPBX7B/19ClN4wzI5CoNc9jkx0PIXEo5iWLk=</Modulus><Exponent>AQAB</Exponent><P>0b5D6oI3mOKKIHgfCrl03vfUTo91UeJyvpZ1l6F6NzUzPDhCG3Sin5dXtxEFejPayLsgLOIMMuqobOzI9wJpBQ==</P><Q>vrxvorDFE3g1cj2kWWWZc2BS7UMf+xxnPhtBR3x3T/DyTEnkEXvGLdRBuUGWKhxUpRcBkcBfAadJjhYUqYBvJQ==</Q><DP>SKYKiDPKZh4xkcWJmwFZxdE5rGxsSoyRCgq7eGXqGy1GLdmerDveCEE3lKVErGtBoL2QC3vQleJJrFDn2wbusQ==</DP><DQ>sIoTPd8lmd6ygVnCq6fZPywRtV9i03a3rIlng3YVrN1UNv5RZUlN5g9HAeRNzA5K3j8MCc6nYQ1ojGWtnDGvLQ==</DQ><InverseQ>rQzqbkXZ9Tmno3ElcliX57Xv4AXyF6yFO1kH4LHwkc8jN5dB9XYEdBIgm43yHFIznvOdc2L9Nkl2nHbFCeAKmg==</InverseQ><D>XA7IN+XP2zPBpS9HlJmcHbWO2NHK07FVODH8R70QPP9bieRNx/4YY6TU5uOc+cZFGw7CVLHJCm0TdMBaGlgxeC/GTwMrCJigxUgaxbvDmxuSpqYqkjoZhgoZAuUct8RaZUN8zNdEsXCqRhbU61U2Ey587RyPQ7varg9hkPicVHE=</D></RSAKeyValue>
NOTE: PRIVATE KEY IS FOR TEST NOTHING VALUEABLE
It seems that it is created in XML format.
In the line RSA.importKey(key) the error is raised as below:
ValueError: RSA key format is not supported
How should I feed that private key to sign data?
I even tried to form RSA key by parsing the XML and do something as the following:
rsakey = Crypto.PublicKey.RSA.construct((root.find('Modulus').text, root.find('Exponent').text,root.find('D').text))
It gives an error like:
assert isinstance(n, long)
AssertionError
RSA needs PEM file format in order to sign data. As my private key was not important! I used an online site to convert XML to PEM (DON'T DO THIS ON REAL PRIVATE KEYS :|). It now works.
My PEM file is now as below:
-----BEGIN RSA PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJxFmZi3itM4BFsr
BRXKXE+pZ2Kc2HFxX/q+N8A+95KPgo0eRJsA7JpSqikuct66SB0K4/sRPsojRpXD
xTcBZd3AnBz5HiNIamjz2MRNl3j+lmtJHnoJ8tgFlitgrr+tWB1c+F4MUzwV+wf9
fQpTeMMyOQqDXPY5MdDyFxKOYli5AgMBAAECgYBcDsg35c/bM8GlL0eUmZwdtY7Y
0crTsVU4MfxHvRA8/1uJ5E3H/hhjpNTm45z5xkUbDsJUsckKbRN0wFoaWDF4L8ZP
AysImKDFSBrFu8ObG5KmpiqSOhmGChkC5Ry3xFplQ3zM10SxcKpGFtTrVTYTLnzt
HI9Du9quD2GQ+JxUcQJBANG+Q+qCN5jiiiB4Hwq5dN731E6PdVHicr6WdZehejc1
Mzw4Qht0op+XV7cRBXoz2si7ICziDDLqqGzsyPcCaQUCQQC+vG+isMUTeDVyPaRZ
ZZlzYFLtQx/7HGc+G0FHfHdP8PJMSeQRe8Yt1EG5QZYqHFSlFwGRwF8Bp0mOFhSp
gG8lAkBIpgqIM8pmHjGRxYmbAVnF0TmsbGxKjJEKCrt4ZeobLUYt2Z6sO94IQTeU
pUSsa0GgvZALe9CV4kmsUOfbBu6xAkEAsIoTPd8lmd6ygVnCq6fZPywRtV9i03a3
rIlng3YVrN1UNv5RZUlN5g9HAeRNzA5K3j8MCc6nYQ1ojGWtnDGvLQJBAK0M6m5F
2fU5p6NxJXJYl+e17+AF8heshTtZB+Cx8JHPIzeXQfV2BHQSIJuN8hxSM57znXNi
/TZJdpx2xQngCpo=
-----END RSA PRIVATE KEY-----
I want to sign a signature using rsa private key and encode it with sha-256
but im always having this error
TypeError: Unicode-objects must be encoded before hashing
Here is the code snippet:
private_key = rsa.PrivateKey.load_pkcs1(open('private.pem', 'rb').read())
signature = rsa.sign(sign, private_key, 'SHA-256')
Can you help me with this?
Encoding to "utf-8" should work for you.
private_key = rsa.PrivateKey.load_pkcs1(open('private_key.pem', 'rb').read())
signature = rsa.sign(sign.encode("utf-8"), private_key, 'SHA-256')
I have pkcs8_rsa_private_key file which generate by openssl from a rsa_private_key.pem file.
I need make a signature by the private key in python, make the same signature with below java code.
public static final String SIGN_ALGORITHMS = "SHA1WithRSA";
public static String sign(String content, String privateKey) {
String charset = "utf-8";
try {
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
Base64.decode(privateKey));
KeyFactory keyf = KeyFactory.getInstance("RSA");
PrivateKey priKey = keyf.generatePrivate(priPKCS8);
java.security.Signature signature = java.security.Signature
.getInstance(SIGN_ALGORITHMS);
signature.initSign(priKey);
signature.update(content.getBytes(charset));
byte[] signed = signature.sign();
return Base64.encode(signed);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
PKCS#8 defines a way to encode and transport secret keys and it is not specific to OpenSSL; PKCS#1 defines a way to use an RSA key (no matter how it was loaded into your application, with PKCS#8 or not) to carry out and verify digital signature on data.
The piece of code you have does three things:
It decodes Base64 into PKCS#8
It decodes PKCS#8 into the actual key in memory (mind you may need to provide a passphrase here)
It performs PKCS#1 v1.5 signature using SHA-1 using said key
It encodes the signature in Base64
The example for PKCS#1 v1.5 signing in the API of PyCrypto does exactly steps #2 and #3.
from Crypto.Signature import PKCS1_v1_5 as pk
from Crypto.Hash import SHA
class Crypt(object):
pkcs8_private_key = RSA.importKey(open('pkcs8_rsa_private_key.pem', 'r').read())
def rsa_sign(cls, des_reqdata):
"""
#:param reqdata: request reqData
"""
h = SHA.new(des_reqdata)
signer = pk.new(cls.pkcs8_private_key)
signature = signer.sign(h)
return base64.b64encode(signature)