Understanding how private keys generate blockchain addresses is crucial for secure and seamless cryptocurrency transactions. Recently, a critical update was made to address a subtle yet significant behavior in web wallets—specifically, how private keys are used to derive wallet addresses under two different cryptographic standards. This article explores the technical distinctions between new and old address formats, the implications for wallet functionality, and how developers can ensure compatibility across systems.
The Core Issue: 0x
Prefix and Address Mismatch
A seemingly minor detail—whether a private key includes or excludes the 0x
prefix—can lead to major discrepancies in address derivation. During routine testing, it was discovered that including 0x
in a private key string could result in generating an entirely different address than expected. This inconsistency posed a risk for users attempting to recover or import wallets.
The root cause lies in how cryptographic functions process input. When a private key starts with 0x
, some functions interpret this as a hexadecimal identifier and strip it before processing. Others do not, leading to mismatched public keys and, consequently, different wallet addresses. To prevent this, our web wallet now standardizes private key handling by removing the 0x
prefix early in the process:
privateKey = privateKey.replace(/^(0x)/, '');
This normalization ensures consistent address generation regardless of user input format.
Address Derivation: Two Standards, Two Methods
Modern blockchain ecosystems support multiple address formats due to evolving cryptographic standards. Our system now supports both legacy (tendermint) and new (ethermint) address derivation methods.
🔹 Legacy Address Format (tendermint/PubKeySecp256k1
)
The legacy method uses SHA-256 + RIPEMD-160 hashing for public key compression:
const hash = sha256ripemd160(publicKeyHex);
const address = encodeAddress(hash, prefix);
This produces addresses compatible with older Tendermint-based chains and uses the tendermint/PubKeySecp256k1
public key type.
👉 Discover how modern wallets handle cross-chain compatibility seamlessly.
🔹 New Address Format (ethermint/PubKeyEthSecp256k1
)
The new standard follows Ethereum’s convention using Keccak-256 hashing:
const publicKey = Buffer.from(secp256k1.publicKeyConvert(new Uint8Array(publicKey1), false)).slice(1);
const hash = createKeccakHash('keccak256').update(publicKey).digest();
return encodeAddressToBech32(hash.slice(-20).toString('hex'), prefix);
This results in Ethermint-compatible addresses and enables EVM interoperability.
Both formats coexist to support backward compatibility while enabling future-proof development.
Transaction Signing: Matching Key Types to Chains
Different address formats require different transaction signing logic. The system dynamically selects the correct signature method based on the address type:
const signature = isPrivatekeyOldAddress
? crypto.signPrivateKeyOldAddress(signBytes.toString("hex"), privateKey)
: crypto.sign(signBytes.toString("hex"), privateKey);
🔐 Signature Differences
- Legacy (Old): Uses SHA-256 hash of the sign bytes.
- New: Applies Keccak-256, aligning with Ethereum’s ECDSA standard.
Public keys are also encoded differently:
- Legacy:
"tendermint/PubKeySecp256k1"
- New:
"ethermint/PubKeyEthSecp256k1"
This ensures nodes correctly validate transactions based on their consensus rules.
Frontend Integration: User Experience & State Management
On the frontend, users must be able to verify their private keys and see both possible derived addresses before proceeding.
Address Validation Workflow
When a user enters a private key:
- Strip any
0x
prefix. - Derive both legacy and new addresses.
- Fetch balances for both.
- Display results for user confirmation.
const oldAddress = crypto.getAddressFromPrivateKeyLegacy(privateKey);
const newAddress = crypto.getAddressFromPrivateKey(privateKey);
Users can then choose which path to follow—ensuring no funds are lost due to format confusion.
👉 See how leading platforms streamline private key management securely.
Path Type Selection
Users can explicitly select their intended derivation path:
selectPathType = (type) => {
window.localStorage.setItem(env.envConfig.privatekeyPathType, type);
this.setState({ pathType: type });
};
This setting persists in local storage, improving UX for returning users.
Session Handling & Global State
Once authenticated, user data—including derived address and keystore—is stored securely:
setUserInSessionStroage(privateKey, keyStore) {
let addr = crypto.getAddressFromPrivateKey(privateKey);
if (privatekeyPathType === 'old') {
addr = crypto.getAddressFromPrivateKeyLegacy(privateKey);
}
// Store in localStorage and global context
}
Global variables like window.OK_GLOBAL.senderAddr
ensure other components can access wallet state without reprocessing.
Cross-Origin Resource Sharing (CORS) & API Endpoints
To maintain security and flexibility, API endpoints are dynamically resolved:
export const DEFAULT = 'https://www.okx.com';
export function getCurrentApiUrl() {
let url = 'https://www.okx.com';
const currentNode = storage.get('currentNode');
if (currentNode && currentNode.httpUrl) url = currentNode.httpUrl;
return url;
}
This allows seamless switching between mainnet, testnet, and custom nodes without hardcoding URLs.
Frequently Asked Questions (FAQ)
Q: What happens if I forget to remove the 0x
prefix from my private key?
A: The system automatically strips the 0x
prefix during validation, so your address will still be generated correctly.
Q: Can I use the same private key for both old and new formats?
A: Yes, but it will produce two different addresses. Always confirm which format your target network expects.
Q: How do I know which address format my chain uses?
A: Check your chain's documentation. Ethermint-based chains use the new Keccak-256 format; older Tendermint chains use SHA-256 + RIPEMD-160.
Q: Is one format more secure than the other?
A: Both are cryptographically secure. The difference lies in compatibility, not security strength.
Q: Will my funds be at risk if I use the wrong format?
A: If you send funds to an incorrectly derived address, recovery may be impossible. Always double-check before transacting.
Q: Can I switch between formats after logging in?
A: Yes—simply log out, select the desired path type, and re-import your private key.
Conclusion
Supporting both legacy and modern address formats is essential for building inclusive, interoperable web wallets. By understanding the nuances of private key processing, hashing algorithms, and signature schemes, developers can prevent user errors and ensure smooth cross-chain experiences.
As blockchain standards continue to evolve, maintaining backward compatibility while embracing new protocols will remain a top priority. Whether you're building dApps or managing digital assets, knowing how your wallet derives addresses empowers you to transact safely and confidently.
👉 Explore next-generation wallet infrastructure built for scalability and security.