Android Question Calculate the java.security.Key

Francesco Maresca

Member
Licensed User
Longtime User
Convert the string to bytes with StringUtils.DecodeBase64 and create the key with KeyGenerator.KeyFromBytes.

Note that you only need the private key.

Hi,
this is my code:
B4X:
    Dim Bconv As ByteConverter
    Dim filetemp As String=File.ReadString(File.DirInternal,"temp.xml")
    Dim bfiletemp() As Byte=Bconv.StringToBytes(filetemp,"UTF8")
    Dim ByteFromPrivKey() As Byte=su.DecodeBase64(privateKey)
    Dim k As KeyGenerator
    k.Initialize("AES")
    k.KeyFromBytes(ByteFromPrivKey)
    Dim sign As Signature
    sign.Initialise("SHA256withECDSA",sign.SIGNATURE_SIGN,k.Key)
    sign.Update(bfiletemp)


My error:
java.lang.ClassCastException: javax.crypto.spec.SecretKeySpec cannot be cast to java.security.PrivateKey





 
Upvote 0

Francesco Maresca

Member
Licensed User
Longtime User
Which line raises the error?

Please post the full error message from the logs.

The Line is :
sign.Initialise("SHA256withECDSA",sign.SIGNATURE_SIGN,k.Key)


** Activity (main) Pause, UserClosed = false **
** Service (starter) Create **
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
main_firma (B4A line: 149)
sign.Initialise("SHA256withECDSA",sign.SIGNATURE_
java.lang.ClassCastException: javax.crypto.spec.SecretKeySpec cannot be cast to java.security.PrivateKey
at anywheresoftware.b4a.agraham.encryption.CipherWrapper$SignaturerWrapper.Initialise(CipherWrapper.java:528)
at b4a.example.main._firma(main.java:750)
at b4a.example.main._activity_create(main.java:370)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
at b4a.example.main.afterFirstLayout(main.java:104)
at b4a.example.main.access$000(main.java:19)
at b4a.example.main$WaitForLayout.run(main.java:82)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5951)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)
 
Upvote 0

Francesco Maresca

Member
Licensed User
Longtime User
With this code:

B4X:
Dim k2 As KeyPairGenerator
    k2.Initialize("RSA",2048)
    k2.PrivateKeyFromBytes(ByteFromPrivKey)
    Dim sign As Signature
    sign.Initialise("SHA256withECDSA",sign.SIGNATURE_SIGN,k2.PrivateKey)
    sign.Update(bfiletemp)

I have this error at line k2.PrivateKeyFromBytes(ByteFromPrivKey):

** Activity (main) Pause, UserClosed = false **
** Service (starter) Create **
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
main_firma (B4A line: 155)
k2.PrivateKeyFromBytes(ByteFromPrivKey)
java.security.spec.InvalidKeySpecException: java.lang.RuntimeException: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag
at com.android.org.conscrypt.OpenSSLKey.getPrivateKey(OpenSSLKey.java:180)
at com.android.org.conscrypt.OpenSSLRSAKeyFactory.engineGeneratePrivate(OpenSSLRSAKeyFactory.java:64)
at java.security.KeyFactory.generatePrivate(KeyFactory.java:187)
at anywheresoftware.b4a.agraham.encryption.CipherWrapper$KeyPairGeneratorWrapper.PrivateKeyFromBytes(CipherWrapper.java:457)
at b4a.example.main._firma(main.java:754)
at b4a.example.main._activity_create(main.java:370)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
at b4a.example.main.afterFirstLayout(main.java:104)
at b4a.example.main.access$000(main.java:19)
at b4a.example.main$WaitForLayout.run(main.java:82)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5951)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)
Caused by: java.lang.RuntimeException: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag
at com.android.org.conscrypt.NativeCrypto.d2i_PKCS8_PRIV_KEY_INFO(Native Method)
at com.android.org.conscrypt.OpenSSLKey.getPrivateKey(OpenSSLKey.java:178)
... 19 more
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
It looks like the private key is invalid or doesn't match the algorithm.

This code works:
B4X:
Dim data() As Byte = Array As Byte(1, 2, 3)
Dim k2 As KeyPairGenerator
k2.Initialize("RSA",2048)
k2.GenerateKey
Dim sign As Signature
sign.Initialise("SHA256withRSA",sign.SIGNATURE_SIGN,k2.PrivateKey)
sign.Update(data)
Dim b() As Byte = sign.Sign
Dim bc As ByteConverter
Log(bc.HexFromBytes(b))
sign.Initialise("SHA256withRSA", sign.SIGNATURE_VERIFY,k2.PublicKey)
sign.Update(data)
Log(sign.Verify(b))
 
Upvote 0

Francesco Maresca

Member
Licensed User
Longtime User
It looks like the private key is invalid or doesn't match the algorithm.

This code works:
B4X:
Dim data() As Byte = Array As Byte(1, 2, 3)
Dim k2 As KeyPairGenerator
k2.Initialize("RSA",2048)
k2.GenerateKey
Dim sign As Signature
sign.Initialise("SHA256withRSA",sign.SIGNATURE_SIGN,k2.PrivateKey)
sign.Update(data)
Dim b() As Byte = sign.Sign
Dim bc As ByteConverter
Log(bc.HexFromBytes(b))
sign.Initialise("SHA256withRSA", sign.SIGNATURE_VERIFY,k2.PublicKey)
sign.Update(data)
Log(sign.Verify(b))

Ok, but I can't create a private key because I read the key from a file

My steps:

1 - The key that is used in a text file (PRIVATEKEY.TXT) and is saved this way:

B4X:
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC2gqnurckKk1Zb
AXqyGDTKBVUg7wyr/WTb5ow0mecadIIOUdiVO+A+jnvRInCNpmMlFWoCX3LXzAv4
ASZX8QmUUd2PXPN+6X21KMAJCdz8/mdmcxYDy+6sgeno9oZ0BUBeoWCPhQ+StBVQ
0TC4hAeNIz6ufYDbuao6CRXvp6lgOCoDkWWJBlHT0/joRpHwWponq3QwAYOF8hnD
f0d4uKNBBSKnDo4W8HBxLOSnOP6jAd5py/w0EdZfsXosIjo0rTa4o6Fo205LSKKG
S9cW4p6O/Zz1GLzqD9FlYzLUAZ3MkExrr1vBeRnx5lzY1acyQqUXyLtVwZYkbSsj
DFMSNo1xAgMBAAECggEACRTVWdAB6enM6ThYn5X+wnKjesEKU2CHbT26ij+CNVnI
wuelrD9PeC1k0dIx4Yp+8nBvVvDi6QP5MHz2KHgQ7vVn3eNVJmJ9487ER27bNSd/
g6SEWuoB1Umdlv71T76XJl5HTLzlOnqFeQD/uJ6xNX+kddA+4jAJ3VtoYQVpsyTi
x26WTx+0ZjXNJ1AaRvEy6sfvFPyXKvfpW2Vov6Qf4M+RR32fLqEM9hcikR6nF01h
wls55CGvQKCaPObOqAtpkrFihPurDD1LbLaLZzFA26e8MejWIpdRMx2iwKanxw7f
NvG7oNZOUtJ3e6K6NKIgtWKjNJ7++K7DjeqQF9N/MQKBgQDYK+w1S6AQBdBCPJwL
Rj4G2R89tem0FcPVkc5AM6uxd7dElqnvucmAnRoGpmSZZz3o5/ckjnnQotR25wXW
9orRQ3UIYZUWGc+iaCni8lkXfAQJ5FX2o2kFjEt1AVKOIOHs5/F7XC+g1pokKn0X
hTL0woK5x8zjTx110w69hTTj5QKBgQDYIw7z+MlJlVG3rqEPLbmD19ywjl9ktUHx
+g0F7mSDfnSQBubhs0CPpoi6V7dBC/+J0iREvRmF6NYxjCctZqMD3p2Vx+g/lHBQ
HLjUDjDQj4NwPOCaM7JaTEU0k4j0D1Ri+7L/hE0SVeC548pTR0tnNL7vAePGF4K3
iSHGCRMCnQKBgG0MGyf3clMi25/OO1lkob2KobvbnHz/zb5awxSX/DCWF5k995O6
wO9kUNCx92V7MzveaEnEpaadvVgNymBaFkTiJpOHxlFTy+49ZYPahR7XrKHg0YyN
elkWIKpxdFfGNrHvf12fb1dPaop79IZ85uuZg6B8Ldss+cuKIJFyNPARAoGAbnD7
ow7tS/xQ1VsWUXs74HLdAhq+A+fa2pq7LNyz370uMqpUL+A4jS67jvxjV4mZ+gK3
Jai68gIX8Rl8q2ZWxhNq0q5jrplbCpSinTjjGK88qo1w91qTODDg7Ay3Xn620B1t
ScOA3m2jd1k+eW9kyEfbiKWejgpVcRNRfrAEVsECgYBg9lanHA3rUZBl7YCGv56z
x+PekCgVQmyl0VLVcq6/Sk2nqFmUmAQogDj2FyIWK1Zrkl2CLIs9z1eMLLspsDmp
lDkepR+fyYDcZPIleFcfkVRMnSuKZ824aj1q6Xsj5//duuV4I8KaLuIdLyuMUGze
c+x/Uh2dd5RnfjTPXhfxlg==

2 - The code

B4X:
    Dim data() As Byte = ArrayAs Byte(1, 2, 3)
    Dim privateKey As String=File.ReadString(File.DirAssets,"PRIVATEKEY.txt") '
    Dim ByteFromPrivKey() As Byte = su.DecodeBase64(privateKey)
    Dim k2 As KeyPairGenerator
    k2.Initialize("RSA",2048)
    k2.PublicKeyFromBytes(ByteFromPrivKey)
    Dim sign As Signature
    sign.Initialise("SHA256withECDSA",sign.SIGNATURE_SIGN,k2.PrivateKey)
    sign.Update(data)

Question:
The key is base64, you must decode it differently?
 
Upvote 0

KMatle

Expert
Licensed User
Longtime User
ASN1_CHECK_TLEN:wrong tag

You have to remove the header/footer (Begin... / End...)

1. Convert the B64-String to Bytes
2. Convert the Bytes to a regular String (take a look how it looks)
3. Remove header/footer
4. Convert to Bytes
5. Load it

See my example: https://www.b4x.com/android/forum/t...o-communicate-with-php-openssl.59445/#content

B4X:
'Convert the Private Key
PrivKeyBytes=su.DecodeBase64(PrivKeyString)
PrivKeyString=Bconv.StringFromBytes(PrivKeyBytes, "UTF8")
Log (ForeignPrivKeyString)
             
PrivKeyString=PrivKeyString.Replace("-----BEGIN PRIVATE KEY-----","")
PrivKeyString=PrivKeyString.Replace("-----END PRIVATE KEY-----","")

Convert "PrivKeyString" back to Bytes and then load it...
 
Upvote 0

Francesco Maresca

Member
Licensed User
Longtime User
You have to remove the header/footer (Begin... / End...)

1. Convert the B64-String to Bytes
2. Convert the Bytes to a regular String (take a look how it looks)
3. Remove header/footer
4. Convert to Bytes
5. Load it

See my example: https://www.b4x.com/android/forum/t...o-communicate-with-php-openssl.59445/#content

B4X:
'Convert the Private Key
PrivKeyBytes=su.DecodeBase64(PrivKeyString)
PrivKeyString=Bconv.StringFromBytes(PrivKeyBytes, "UTF8")
Log (ForeignPrivKeyString)
          
PrivKeyString=PrivKeyString.Replace("-----BEGIN PRIVATE KEY-----","")
PrivKeyString=PrivKeyString.Replace("-----END PRIVATE KEY-----","")

Convert "PrivKeyString" back to Bytes and then load it...
You have to remove the header/footer (Begin... / End...)

1. Convert the B64-String to Bytes
2. Convert the Bytes to a regular String (take a look how it looks)
3. Remove header/footer
4. Convert to Bytes
5. Load it

See my example: https://www.b4x.com/android/forum/t...o-communicate-with-php-openssl.59445/#content

B4X:
'Convert the Private Key
PrivKeyBytes=su.DecodeBase64(PrivKeyString)
PrivKeyString=Bconv.StringFromBytes(PrivKeyBytes, "UTF8")
Log (ForeignPrivKeyString)
           
PrivKeyString=PrivKeyString.Replace("-----BEGIN PRIVATE KEY-----","")
PrivKeyString=PrivKeyString.Replace("-----END PRIVATE KEY-----","")

Convert "PrivKeyString" back to Bytes and then load it...

Hi,
i have read your post but i have the same problem.

In my case, I have to read the key I generated using openssl, without having to go through the web, but by reading it directly from the generated .pem file.
Can you give me an example?
 
Upvote 0

KMatle

Expert
Licensed User
Longtime User
Hi,
i have read your post but i have the same problem.

In my case, I have to read the key I generated using openssl, without having to go through the web, but by reading it directly from the generated .pem file.
Can you give me an example?

Can you post the *.pem file?
 
Upvote 0

Francesco Maresca

Member
Licensed User
Longtime User
Can you post the *.pem file?

I have Solved with this code:

B4X:
     Dim Bconv As ByteConverter
     Dim su As StringUtils
     Dim PrivateKeyB(0) As Byte
     Dim PrivateKeyS As String
     Dim k As KeyPairGenerator

        K.Initialize("RSA", 2048)
     PrivateKeyS = File.ReadString(File.DirAssets, "privatekey.pem").Trim
     PrivateKeyB = su.DecodeBase64(PrivateKeyS)
     k.PrivateKeyFromBytes(PrivateKeyB)


In my key i have removed BEGIN PRIVATE KEY and END PRIVATE KEY

I did further checks and found that I have a different behavior with a similar key to this
----- BEGIN RSA PRIVATE KEY -----
CODE IN BASE64
----- END RSA PRIVATE KEY -----

In this case in line
B4X:
  k.PrivateKeyFromBytes(PrivateKeyB)
I have the usual error "java.security.spec.InvalidKeySpecException: java.lang.RuntimeException: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag"

To solve this, I have to initialize the key with another algorithm, or there is a function that allows me to convert the RSA PRIVATE KEY in PRIVATE KEY?
 
Upvote 0

KMatle

Expert
Licensed User
Longtime User
I will take a look to the key this evening...

Did your create it this way?

B4X:
openssl genrsa  -out PrivateKey.pem 2048 'or 4096/8192
openssl pkcs8 -topk8 -inform pem -in PrivateKey.pem -outform pem -nocrypt -out C:/xampp/htdocs/rsa/PrivateKey.pem
openssl rsa -pubout -in PrivateKey.pem -out C:/xampp/htdocs/rsa/PublicKey.pem

By the way: It looks too long for 2048 bit (4096 or 8192?)
 
Upvote 0

Francesco Maresca

Member
Licensed User
Longtime User
I will take a look to the key this evening...

Did your create it this way?

B4X:
openssl genrsa  -out PrivateKey.pem 2048 'or 4096/8192
openssl pkcs8 -topk8 -inform pem -in PrivateKey.pem -outform pem -nocrypt -out C:/xampp/htdocs/rsa/PrivateKey.pem
openssl rsa -pubout -in PrivateKey.pem -out C:/xampp/htdocs/rsa/PublicKey.pem

By the way: It looks too long for 2048 bit (4096 or 8192?)

The private key was given to me and I did not create myself but it's long 2048 bit.

By running this command
B4X:
openssl pkcs8 -topk8 -inform pem -in PrivateKey.pem -outform pem -nocrypt -out C:/xampp/htdocs/rsa/PrivateKey.pem
I have convert the RSA PRIVATE KEY in PRIVATE KEY (pkcs8 format) and i solved the problem.

It's possible convert the RSA PRIVATE KEY in pkcs8 format with B4A command?
 
Upvote 0

KMatle

Expert
Licensed User
Longtime User
Take a look at the pem file:

Unbenannt.JPG


1. It looks like a Base64-String
2. There's a header and a footer (which is not Base64)
3. There are LF's at the end of each line (which is not Base64, too)

What we need is a clean Base64 string:

B4X:
    Dim Pem As String
    Dim PemBytes() As Byte
  
    Pem=File.ReadString(File.DirApp,"pem.pem") 'read the pem file into a string
    Pem=Pem.Replace("-----BEGIN PRIVATE KEY-----","")
    Pem=Pem.Replace("-----END PRIVATE KEY-----","")
    Pem=Pem.Replace(CRLF,"")

After this it is:

B4X:
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDx4a//WIdrQfPjKMlNCXSHuISFd7CkIkqPN14EKbEC9EvsA59Ct6qy4jkG8LaajcX07bOSdJVkNMpjLsNE8sTdS4MNjwkcsmqjnMpnKCcR0UKwnShTZyUjevceFSeiopWEZ2LS91qPL0dg1S5NCgV/ds0E5jcx/KRsdwS35npjzRWnV4gFwCcVOKXm/3L5lRBB+y6PT2P9bRGKctusOlkuImK1BT8o0/ohATnlLB7uEfB+AuFJwYP/KUYVSYGNjuBklh1wCjhuMsGWeoU2uZcrN8F7D/jKZ/nsKefVABw6ELP0NP9EsHZSQ/i77szP1NjxdOAW5qdlsPNtEDE3th9pAgMBAAECggEAaIp3i7ASj0vpAePt5OrSP5qDREAvyzC68t0mODxgsfsuGSqTmb1R/JCDvzkoYvIlfa+CrijPLIkYc/eRE+qtJUvur1yDvrBq...

This is a clean Base64-string :)

1. Convert it into Bytes
2. Load it

Full code:

B4X:
    Dim Pem As String
    Dim PemBytes() As Byte
  
    Pem=File.ReadString(File.DirApp,"pem.pem") 'load from file into string
    Pem=Pem.Replace("-----BEGIN PRIVATE KEY-----","")
    Pem=Pem.Replace("-----END PRIVATE KEY-----","")
    Pem=Pem.Replace(CRLF,"")
    Log(Pem)
      
    Dim su As StringUtils
    PemBytes=su.DecodeBase64(Pem) 'Base64 -> Bytes
  
    Dim TestC As Cipher
    Dim TestKPG As KeyPairGenerator
    TestC.Initialize("RSA/ECB/PKCS1Padding")
       TestKPG.Initialize("RSA", 2048)
    TestKPG.PrivateKeyFromBytes(PemBytes) 'Works!


Note: Usually you get the PUBLIC key, not the private one (you encrypt with it and it is DEcrypted with the private key). So if two programs use it, there will be 2 Public- and 2 Private Keys!
 
Upvote 0
Top