4

This is my server public key :

UlNBMQAIAAADAAAAAAEAAAAAAAAAAAAAAQABupDgHg710Jh4QwJriIdrY+6yyZme0e0FSQ1EFO3JEmiT+DXRLgU7CcgqGqLhosqYV7Rm1/H0I0ugFBk4zisPbgIb3epyMCcjnTgknRYddtIl9jNS8Z91/1SJ5bY0FkIRFJLHSCEcu1Un09w+gpWRoeAhSc87EMGngUZixAcyoDeYsW0mM1IlH44flo76wXERadmtAd9KFN0nYTjMwkIDyc5B9I2zvSjOQ+p54+6dl6o6nOalCWJg8V137ZMwQCk/4Tmp4C52d0AzYjEeU9gQowkrm7DgjLthd4ew/kY5a/8JfsWMJhajDPgzBV5fFJMbNL1h0fmtG8QpH5OtWukDhQ==

And Encryption Code :

 byte[] publicBytes = Base64.decode(PUBLIC_KEY, Base64.DEFAULT);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey pubKey = keyFactory.generatePublic(keySpec);
            Cipher cipher = Cipher.getInstance("RSA"); //or try with "RSA"
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            encrypted = cipher.doFinal(txt.getBytes());
            encoded = Base64.encodeToString(encrypted, Base64.DEFAULT);

i get this error when i try to encrypt :

java.security.spec.InvalidKeySpecException: java.lang.RuntimeException: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag

what's wrong with this ?

Steve
  • 94
  • 1
  • 5

1 Answers1

2

As already commented, this is a proprietary Microsoft format for public RSA keys, BCRYPT_RSAPUBLIC_BLOB:

BCRYPT_RSAKEY_BLOB
PublicExponent[cbPublicExp]          // Big-endian.
Modulus[cbModulus]                   // Big-endian.

with

typedef struct _BCRYPT_RSAKEY_BLOB {
    ULONG Magic;                      // identifies the type, e.g. BCRYPT_RSAPUBLIC_MAGIC for an RSA public key
    ULONG BitLength;                  // size, in bits, of the key
    ULONG cbPublicExp;                // size, in bytes, of the exponent of the key
    ULONG cbModulus;                  // size, in bytes, of the modulus of the key
    ULONG cbPrime1;                   // size, in bytes, of the first prime number of the key. This is only used for private key BLOBs
    ULONG cbPrime2;                   // size, in bytes, of the second prime number of the key. This is only used for private key BLOBs
} BCRYPT_RSAKEY_BLOB;

The values in BCRYPT_RSAKEY_BLOB have the little endian format, the exponent and the modulus the big endian format. BCRYPT_RSAPUBLIC_MAGIC has the value 826364754 or 0x31415352 as big endian and 0x52534131 as little endian. The latter corresponds to the ASCII encoding of the string RSA1.

The posted key is after Base64 decoding in hexadecimal format:

525341310008000003000000000100000000000000000000010001ba90e01e0ef5d0987843026b88876b63eeb2c9999ed1ed05490d4414edc9126893f835d12e053b09c82a1aa2e1a2ca9857b466d7f1f4234ba0141938ce2b0f6e021bddea723027239d38249d161d76d225f63352f19f75ff5489e5b6341642111492c748211cbb5527d3dc3e829591a1e02149cf3b10c1a7814662c40732a03798b16d263352251f8e1f968efac1711169d9ad01df4a14dd276138ccc24203c9ce41f48db3bd28ce43ea79e3ee9d97aa3a9ce6a5096260f15d77ed933040293fe139a9e02e7677403362311e53d810a3092b9bb0e08cbb617787b0fe46396bff097ec58c2616a30cf833055e5f14931b34bd61d1f9ad1bc4291f93ad5ae90385

or separated into its individual components:

little endian   big endian
52534131        0x31415352 
00080000        0x0800     = 2048 bits
03000000        0x  03     =    3 bytes 
00010000        0x0100     =  256 bytes
00000000    
00000000

big endian
010001
ba90e01e0ef5d0987843026b88876b63eeb2c9999ed1ed05490d4414edc9126893f835d12e053b09c82a1aa2e1a2ca9857b466d7f1f4234ba0141938ce2b0f6e021bddea723027239d38249d161d76d225f63352f19f75ff5489e5b6341642111492c748211cbb5527d3dc3e829591a1e02149cf3b10c1a7814662c40732a03798b16d263352251f8e1f968efac1711169d9ad01df4a14dd276138ccc24203c9ce41f48db3bd28ce43ea79e3ee9d97aa3a9ce6a5096260f15d77ed933040293fe139a9e02e7677403362311e53d810a3092b9bb0e08cbb617787b0fe46396bff097ec58c2616a30cf833055e5f14931b34bd61d1f9ad1bc4291f93ad5ae90385

The last two portions are the exponent:

0x010001 = 65537

and the modulus

0xba90e01e0ef5d0987843026b88876b63eeb2c9999ed1ed05490d4414edc9126893f835d12e053b09c82a1aa2e1a2ca9857b466d7f1f4234ba0141938ce2b0f6e021bddea723027239d38249d161d76d225f63352f19f75ff5489e5b6341642111492c748211cbb5527d3dc3e829591a1e02149cf3b10c1a7814662c40732a03798b16d263352251f8e1f968efac1711169d9ad01df4a14dd276138ccc24203c9ce41f48db3bd28ce43ea79e3ee9d97aa3a9ce6a5096260f15d77ed933040293fe139a9e02e7677403362311e53d810a3092b9bb0e08cbb617787b0fe46396bff097ec58c2616a30cf833055e5f14931b34bd61d1f9ad1bc4291f93ad5ae90385

In Java the public key can be created with the class RSAPublicKeySpec. This class has a constructor that expects exponent and modulus, see e.g. here and here.

Update:

As mentioned in the comment of @Maarten Bodewes, the following must be considered when creating modulus and exponent as BigInteger: Modulus and exponent are positive values. However, Java uses the 2's complement for the representation of integers, so that the first byte additionally contains the information about the sign (i.e. if the leftmost byte is larger than 0x79, the value is negative). To take account of this, a 0x00 byte can be prepended if the leftmost byte is larger than 0x79. Alternatively, there are corresponding constructors, e.g. BigInteger(String val, int radix), if the data are available as hex-strings (the sign is taken into account in the string-parameter as optional +/-), or BigInteger(int signum, byte[] magnitude), if the data are available as byte arrays (the sign is taken into account in the int-parameter). Since in the current case the data are probably available as hex-strings, the following is suitable (e.g. for the modulus):

BigInteger modulus = new BigInteger("ba90e01e...5ae90385", 16);
Topaco
  • 40,594
  • 4
  • 35
  • 62