// SPDX-License-Identifier: GPL-3.0-only // Copyright (c) 2022, Sylvain Huet, Ambermind // Minimacy (r) System use core.crypto.hash;; use core.crypto.rsa;; // pkcs1 const _HEADER=10;; fun _inputBlockSize (nbits, forEncryption)= ((nbits+7)>>3) - forEncryption;; fun _outputBlockSize(nbits, forEncryption)= ((nbits+7)>>3) + forEncryption -1 ;; fun _pkcs1InputBlockSize(nbits, forEncryption)= _inputBlockSize( nbits, forEncryption)-forEncryption*_HEADER;; fun _pkcs1OutputBlockSize(nbits, forEncryption)= _outputBlockSize( nbits, forEncryption)-(1-forEncryption)*_HEADER;; // fexp B->B is supposed to encode the bignum with the key fun _pkcs1Encrypt(N, data, forPrivateKey, fexp)= let strLength(data) -> dataLen in let bigNbits(N) -> nbits in let _inputBlockSize(nbits, 1) -> blockLen in let bytesCreate(blockLen, 0xff) -> block in let blockLen-dataLen-1 -> headerLen in ( if forPrivateKey then bytesSet(block, 0, 0x01) else ( bytesRand(block, 0, headerLen); bytesSet(block, 0, 0x02); for i=1;i bignum in let call fexp(bignum) -> encoded in bigSerialize(encoded, _pkcs1OutputBlockSize(nbits, 1)) );; fun _pkcs1Decrypt(N, data, forPrivateKey, fexp)= let bigNbits(N) -> nbits in let bigDeserialize(data) -> bignum in let call fexp(bignum) -> decoded in let _outputBlockSize(nbits, 0) -> blockLen in let bigSerialize(decoded, blockLen) -> block in let strGet(block, 0) -> type in if (!forPrivateKey && type==1)||(forPrivateKey && type==2) then // no else, this returns nil when wrong header byte let strCharPos(block, 0, 1) -> i in if i<>nil then strTail(block, i+1);; fun _pkcs1LoopEncrypt(N, data, i, blockLen, forPrivateKey, fexp)= if inil then let bigNbits(N) -> nbits in let _pkcs1InputBlockSize(nbits, forEncryption) -> inputBlockLen in let strLength(data) -> dataLen in if (forEncryption<>0)||(0==(dataLen%inputBlockLen)) then // no else, this returns nil when decrypting data with wrong size strListConcat(if forEncryption<>0 then _pkcs1LoopEncrypt(N, data, 0, inputBlockLen, forPrivateKey, fexp) else _pkcs1LoopDecrypt(N, data, 0, inputBlockLen, forPrivateKey, fexp));; fun pkcs1EncryptPubRsa(rsa, data) = _pkcs1Process(rsaModulus(rsa), data, 1, false, lambda(msg) = bigExpMod(msg, rsaPubExp(rsa), rsaModulus(rsa)));; fun pkcs1DecryptPubRsa(rsa, data) = _pkcs1Process(rsaModulus(rsa), data, 0, false, lambda(msg) = bigExpMod(msg, rsaPubExp(rsa), rsaModulus(rsa)));; fun pkcs1EncryptPrivRsa(rsa, data)= _pkcs1Process(rsaModulus(rsa), data, 1, true, lambda(msg) = rsaComputePrivateExpAndCheck(rsa, msg));; fun pkcs1DecryptPrivRsa(rsa, data)= _pkcs1Process(rsaModulus(rsa), data, 0, true, lambda(msg) = rsaComputePrivateExpAndCheck(rsa, msg));; fun rsaPkcs1Sign(rsa, data, magic, fHash)= let strConcat(strFromHex(magic), call fHash(data)) -> hash in pkcs1EncryptPrivRsa(rsa, hash);; fun rsaPkcs1SignatureCheck(rsa, data, signature, magic, fHash)= let strConcat(strFromHex(magic), call fHash(data)) -> hash in if hash<>nil then let pkcs1DecryptPubRsa(rsa, signature) -> decode in hash==decode;;