Convert PEM format Curve25519 ECDH Keys with long length base64 string?

 let privateKey = Curve25519.KeyAgreement.PrivateKey() let publicKey = privateKey.publicKey

than what I do next? my requirement keys are like

Public Key: -——BEGIN PUBLIC KEY-----MIIBMTCB6gYHKoZIzj0CATCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////////////////7TBEBCAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqYSRShRAQge0Je0Je0Je0Je0Je0Je0Je0Je0Je0Je0JgtenHcQyGQEQQQqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAAAAAAAAAAAFN753qL3nNZYEmMaXPXT7QIBCANCAARMyjhxmqctNgQJS5yef637I1SMM+Yg9PZ6VKF83hgCDH13bayEHj8I1nEPVO5pfyqATxOcOQS110iA9QJTEpsI-----END PUBLIC KEY-----

Private Key:

-----BEGIN PRIVATE KEY-----MIICRwIBADCB6gYHKoZIzj0CATCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////////////////7TBEBCAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqYSRShRAQge0Je0Je0Je0Je0Je0Je0Je0Je0Je0Je0JgtenHcQyGQEQQQqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAAAAAAAAAAAFN753qL3nNZYEmMaXPXT7QIBCASCAVMwggFPAgEBBCAOeSuzq+O1tPlhPZj4KZdfAq5Z0+yca15ukbUuwsyJQKCB4TCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////////////////7TBEBCAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqYSRShRAQge0Je0Je0Je0Je0Je0Je0Je0Je0Je0Je0JgtenHcQyGQEQQQqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAAAAAAAAAAAFN753qL3nNZYEmMaXPXT7QIBCKFEA0IABG56w6jtAyb2T6oguKNN6HvLPQdT0Mms8gCepW51pobrDT/WfXJKfFr5fRuNalS+YkDQggoc7xtpYFin0ELidYw=-----END PRIVATE KEY-----

Replies

For those reading along at home, here’s a link back to satyaaakana’s original thread.

It would really help if you could post code snippets as code. That means using back quote limiters for inline code and triple back quotes for code blocks. Or select the text and click either the Inline Code or Code Block button.

Let’s focus on your public key at the moment. If I take the Base64 you posted above, decode it, and then dump it with dumpasn1, I see this:

% xxd public.asn1 
00000000: 3082 0131 3081 ea06 072a 8648 ce3d 0201  0..10....*.H.=..
00000010: 3081 de02 0101 302b 0607 2a86 48ce 3d01  0.....0+..*.H.=.
00000020: 0102 207f ffff ffff ffff ffff ffff ffff  .. .............
00000030: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000040: ffff ed30 4404 202a aaaa aaaa aaaa aaaa  ...0D. *........
00000050: aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa  ................
00000060: aaaa 9849 14a1 4404 207b 425e d097 b425  ...I..D. {B^...%
00000070: ed09 7b42 5ed0 97b4 25ed 097b 425e d097  ..{B^...%..{B^..
00000080: b426 0b5e 9c77 10c8 6404 4104 2aaa aaaa  .&.^.w..d.A.*...
00000090: aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa  ................
000000a0: aaaa aaaa aaaa aaaa aaad 245a 20ae 19a1  ..........$Z ...
000000b0: b8a0 86b4 e01e dd2c 7748 d14c 923d 4d7e  .......,wH.L.=M~
000000c0: 6d7c 61b2 29e9 c5a2 7ece d3d9 0220 1000  m|a.)...~.... ..
000000d0: 0000 0000 0000 0000 0000 0000 0000 14de  ................
000000e0: f9de a2f7 9cd6 5812 631a 5cf5 d3ed 0201  ......X.c.\.....
000000f0: 0803 4200 044c ca38 719a a72d 3604 094b  ..B..L.8q..-6..K
00000100: 9c9e 7fad fb23 548c 33e6 20f4 f67a 54a1  .....#T.3. ..zT.
00000110: 7cde 1802 0c7d 776d ac84 1e3f 08d6 710f  |....}wm...?..q.
00000120: 54ee 697f 2a80 4f13 9c39 04b5 d748 80f5  T.i.*.O..9...H..
00000130: 0253 129b 08                             .S...
% dumpasn1 -p -a public.asn1 
SEQUENCE {
  SEQUENCE {
    OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
    SEQUENCE {
      INTEGER 1
      SEQUENCE {
        OBJECT IDENTIFIER prime-field (1 2 840 10045 1 1)
        INTEGER
          7F FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
          FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ED
        }
      SEQUENCE {
        OCTET STRING
          2A AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA
          AA AA AA AA AA AA AA AA AA AA AA 98 49 14 A1 44
        OCTET STRING
          7B 42 5E D0 97 B4 25 ED 09 7B 42 5E D0 97 B4 25
          ED 09 7B 42 5E D0 97 B4 26 0B 5E 9C 77 10 C8 64
        }
      OCTET STRING
        04 2A AA AA AA AA AA AA AA AA AA AA AA AA AA AA
        AA AA AA AA AA AA AA AA AA AA AA AA AA AA AD 24
        5A 20 AE 19 A1 B8 A0 86 B4 E0 1E DD 2C 77 48 D1
        4C 92 3D 4D 7E 6D 7C 61 B2 29 E9 C5 A2 7E CE D3
        D9
      INTEGER
        10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
        14 DE F9 DE A2 F7 9C D6 58 12 63 1A 5C F5 D3 ED
      INTEGER 8
      }
    }
  BIT STRING
    04 4C CA 38 71 9A A7 2D 36 04 09 4B 9C 9E 7F AD
    FB 23 54 8C 33 E6 20 F4 F6 7A 54 A1 7C DE 18 02
    0C 7D 77 6D AC 84 1E 3F 08 D6 71 0F 54 EE 69 7F
    2A 80 4F 13 9C 39 04 B5 D7 48 80 F5 02 53 12 9B
    08
  }

This is not a Curve 25519 key. It’s 65 bytes long but Curve 25519 are always 32 bytes long. For example, this code:

import CryptoKit
import Foundation

func main() {
    let privateKey = Curve25519.KeyAgreement.PrivateKey()
    let publicKey = privateKey.publicKey
    debugPrint(publicKey.rawRepresentation as NSData)
}

main()

prints this:

<678742c8 8d39c2ef 3116d40b 51ec20da 0ae07d07 16f78166 a7130953 0588bf6e>

Notably, the leading 04 in your key suggests that the is actually a flavour of SECG.

Also note that the prime-field indicates that it’s using a custom curve. Such keys are not supported on Apple platforms.

So, in summary, I think you’re having problems here because you think you’re trying to generate a Curve 25519 key but the example you posted isn’t in that format.

ps For more background on the tools and techniques I used to investigate this, see my On Cryptographic Key Formats post.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thank you Quinn, After generating public and private keys

need to generate PEM format like,

-----BEGIN PUBLIC KEY-----
// base64String
-----END PUBLIC KEY-----
-----BEGIN PRIVATE KEY-----
// base64String
-----END PRIVATE KEY-----

This is the java code for generating keys and convert pem format , required same for this:

@Log@Servicepublic class ECCService {    @Value("${forwardsecrecy.ecc.curve:Curve25519}")    String curve;    
@Value("${forwardsecrecy.ecc.algorithm:EC}")    String algorithm;    @Value("${forwardsecrecy.ecc.keyDerivationAlgorithm:ECDH}")    
String keyDerivationAlgorithm;    @Value("${forwardsecrecy.ecc.provider:BC}")    String provider;   
 @Value("${forwardsecrecy.ecc.keyExpiryHrs:24}")    int keyExpiry;    

    private KeyPair generateKey()     throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {     
   KeyPairGenerator kpg;      
  kpg =        KeyPairGenerator.getInstance(algorithm, provider);
        X9ECParameters ecP = CustomNamedCurves.getByName(curve); 
       ECParameterSpec ecSpec = EC5Util.convertToSpec(ecP);        
kpg.initialize(ecSpec);
        final KeyPair kp = kpg.genKeyPair();       
 log.info("Key pair generated " + kp.getPublic().getAlgorithm());       
 return kp;    }

    public SerializedKeyPair getKeyPair()            throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
        final KeyPair kp = this.generateKey();    
    final String privateKey = this.getPEMEncodedStream(kp.getPrivate(),true);     
   final String publicKey = this.getPEMEncodedStream(kp.getPublic(), false);  
      Date date = new Date();      
  Calendar cl = Calendar. getInstance();     
   cl.setTime(date);      
  cl.add(Calendar.HOUR, keyExpiry);        
TimeZone tz = TimeZone.getTimeZone("UTC");        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); // Quoted "Z" to indicate UTC, no timezone offset        df.setTimeZone(tz);     
   String expiryAsISO = df.format(cl.getTime());  
      final DHPublicKey dhPublicKey = new DHPublicKey(expiryAsISO,"",publicKey);   
     final KeyMaterial keyMaterial = new KeyMaterial(keyDerivationAlgorithm,curve,"",dhPublicKey);        final SerializedKeyPair serializedKeyPair = new SerializedKeyPair(privateKey, keyMaterial);   
     return serializedKeyPair;    }

    private String getPEMEncodedStream(final Key key, boolean privateKey) {
        final PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key.getEncoded());   
     final StringBuilder sb = new StringBuilder();     
   final String keyType = privateKey ? "PRIVATE" : "PUBLIC";        sb.append("-----BEGIN " + keyType + " KEY-----");        sb.append(new String(Base64.getEncoder().encode(pkcs8KeySpec.getEncoded())));        sb.append("-----END " + keyType + " KEY-----");        return sb.toString();    }
}

I’m sorry but you really need to format your posts in a way that makes them easy to read. I’ve a limited amount of time to spend on DevForums and it’s important that I use that time efficiently.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"