1

I'm trying to create an app that uses authentication with ecdsa keys but I faced with some problem with key generation and reading it. When I make request to the authentication controller it shows me such exception:

java.security.InvalidKeyException: IOException : algid parse error, not a sequence

That's what I did:

  1. I generated private key with this command:
$ openssl ecparam -name secp256k1 -genkey -noout -out private_key.pem 

Then I got this pem key:

-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIMdy2DTdd7ZF/oVjd69ddslzyy1GsBSuehz0uEGVYtk5oAcGBSuBBAAK
oUQDQgAEnZaAiTxwX93hzPMs4+VVJ1tGK1wv6SWN4Ac/59fQx6bBY0MO6VTzofna
gomVhx/xcyu7KQVmNVTgW51w7BSfNg==
-----END EC PRIVATE KEY-----
  1. I wrote a class that gets private key to use it later

RSAService.java

public class RSAService {

    public static PrivateKey getPrivateKey(String fileName)
            throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        return getPrivateKeyFromString(getKey(fileName));
    }

    private static String getKey(String fileName) throws IOException {
        StringBuilder strKeyPem = new StringBuilder();
        String line;
        try (BufferedReader bf = new BufferedReader(new FileReader(fileName))) {
            while ((line = bf.readLine()) != null) {
                strKeyPem.append(line).append("\n");
            }
        }
        return strKeyPem.toString();
    }

    private static PrivateKey getPrivateKeyFromString(String key)
            throws  NoSuchAlgorithmException, InvalidKeySpecException {
        String privateKeyPem = key;
        privateKeyPem = privateKeyPem.replace("-----BEGIN EC PRIVATE KEY-----", "");
        privateKeyPem = privateKeyPem.replace("-----END PRIVATE KEY-----", "");
        privateKeyPem = privateKeyPem.replace("\n", "");
        byte[] encoded = Base64.decodeBase64(privateKeyPem);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
        return kf.generatePrivate(keySpec); //Here's exception is throwing
    }
}
  1. Then I use this class in JWTService to generate the jwt token:

JWTService.java

@Service
public class JWTService {

    public String extractUsername(String token)
            throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        return extractClaim(token, Claims::getSubject);
    }

    public <T> T extractClaim(String token, Function<Claims, T> claimResolver)
            throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        final Claims claims = extractAllClaims(token);
        return claimResolver.apply(claims);
    }

    public String generateToken(UserDetails userDetails)
            throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        return generateToken(new HashMap<>(), userDetails);
    }

    public String generateToken(Map<String, Object> claims, UserDetails userDetails)
            throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        PrivateKey privateKey =  RSAService.getPrivateKey(PathConfig.PRIVATE_KEY_CONFIG);
        return Jwts
                .builder()
                .setClaims(claims)
                .setSubject(userDetails.getUsername())
                .signWith(privateKey, SignatureAlgorithm.ES256)
                .compact();
    }

    public boolean isTokenValid(String token, UserDetails userDetails)
            throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        final String username = extractUsername(token);
        return username.equals(userDetails.getUsername());
    }

    private Claims extractAllClaims(String token)
            throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        return Jwts
                .parserBuilder()
                .setSigningKey(RSAService.getPublicKey(PathConfig.PUBLIC_KEY_CONFIG))
                .build()
                .parseClaimsJws(token)
                .getBody();
    }
}

So what can be the problem? If you know, please tell me, I'd really appreciate it!

Cross
  • 497
  • 1
  • 3
  • 13
  • 1
    Your private key is in SEC1 format and not in PKCS#8 format, so `PKCS8EncodedKeySpec` won't work. Convert the key e.g. with OpenSSL from SEC1 to the required PKCS#8 format (`openssl pkcs8 -topk8 -nocrypt...`) or use e.g. BouncyCastle to import the SEC1 key directly ([here](https://stackoverflow.com/a/41947163/9014097)). – Topaco Jul 30 '23 at 11:22
  • @Topaco Thank you very much! Now everything is working! – Cross Jul 31 '23 at 09:26

0 Answers0