// swift-tools-version:6.2import PackageDescription let package = Package( name: "howto", platforms: [.macOS(.v15)], dependencies: [ .package(url: "https://github.com/apple/swift-crypto.git", exact: "5.0.3"), ], targets: [ .executableTarget(name: "generate", dependencies: [.product(name: "Crypto", package: "swift-crypto")]), ]) import Cryptoimport Foundation let privateKey = P256.Signing.PrivateKey() // random, from the system CSPRNG // owner-only file: create it with mode 0600 before any key material is writtenguard FileManager.default.createFile(atPath: "key.pem", contents: nil, attributes: [.posixPermissions: 0o600]) else { fatalError("cannot create key.pem")}try Data((privateKey.pemRepresentation + "\n").utf8).write(to: URL(fileURLWithPath: "key.pem")) // "BEGIN PRIVATE KEY" let publicPEM = privateKey.publicKey.pemRepresentation + "\n" // "BEGIN PUBLIC KEY" (SPKI)try Data(publicPEM.utf8).write(to: URL(fileURLWithPath: "pub.pem"))print(publicPEM, terminator: "") How it works
P256.Signing.PrivateKey()draws a new key from the system's secure random source;P384andP521have the same API.pemRepresentationwrites PKCS#8 (BEGIN PRIVATE KEY) andpublicKey.pemRepresentationwrites SPKI (BEGIN PUBLIC KEY); the run checks withopenssl pkeythat they belong together and name P-256.FileManager.createFile(..., attributes: [.posixPermissions: 0o600])creates the empty key file owner-only, and the non-atomicwrite(to:)that follows keeps that mode.derRepresentationandx963Representationgive the same keys as DER or as raw SEC1 bytes, for APIs that do not take PEM.
Gotchas
write(to:options: .atomic)writes a temporary file and renames it over the target — the result has the default mode (0644 in the run's probe), not the 0600 set bycreateFile. Write private keys non-atomically into a file created with the right permissions.pemRepresentationhas no trailing newline. Append one, or concatenating PEM files and comparing them with other tools' output fails.- secp256k1 is not part of CryptoKit or swift-crypto; Bitcoin and Ethereum keys need a dedicated library (for example one built on libsecp256k1).
- On Apple devices, consider
SecureEnclave.P256.Signing.PrivateKey(): the key never leaves the hardware, so there is no PEM to write — only an opaquedataRepresentationfor the same device.